xorg_driver.c revision 3905119b4743eb5d284236cc237ee2c19ae3c5c8
17a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin/*
27a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
37a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * All Rights Reserved.
47a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
57a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * Permission is hereby granted, free of charge, to any person obtaining a
67a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * copy of this software and associated documentation files (the
77a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * "Software"), to deal in the Software without restriction, including
87a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * without limitation the rights to use, copy, modify, merge, publish,
97a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * distribute, sub license, and/or sell copies of the Software, and to
101050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth * permit persons to whom the Software is furnished to do so, subject to
117a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * the following conditions:
127a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
131050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth * The above copyright notice and this permission notice (including the
147a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * next paragraph) shall be included in all copies or substantial portions
157a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * of the Software.
167a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
177a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
197a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
207a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
217a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
227a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
237a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
247a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
257a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
267a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * Author: Alan Hourihane <alanh@tungstengraphics.com>
277a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin * Author: Jakob Bornecrantz <wallbraker@gmail.com>
287a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin *
297a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin */
307a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
317a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
327a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xorg-server.h"
337a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86.h"
347a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86_OSproc.h"
357a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "compiler.h"
367a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86RAC.h"
377a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86PciInfo.h"
387a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86Pci.h"
397a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86Resources.h"
407a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "mipointer.h"
417a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "micmap.h"
427a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include <X11/extensions/randr.h>
437a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "fb.h"
447a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "edid.h"
457a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86i2c.h"
467a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86Crtc.h"
477a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "miscstruct.h"
487a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "dixstruct.h"
497a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include "xf86xv.h"
507a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include <X11/extensions/Xv.h>
517a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#ifndef XSERVER_LIBPCIACCESS
527a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#error "libpciaccess needed"
537a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#endif
547a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
557a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin#include <pciaccess.h>
567a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
57eabcf7e1d4c2be34653a936cff93d0872fe929ddDouglas Gregor#include "xorg_tracker.h"
58eabcf7e1d4c2be34653a936cff93d0872fe929ddDouglas Gregor#include "xorg_winsys.h"
597a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
607a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic void AdjustFrame(int scrnIndex, int x, int y, int flags);
617a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool CloseScreen(int scrnIndex, ScreenPtr pScreen);
627a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool EnterVT(int scrnIndex, int flags);
637a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool SaveHWState(ScrnInfoPtr pScrn);
647a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool RestoreHWState(ScrnInfoPtr pScrn);
657a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
667a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin
677a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic ModeStatus ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
687a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin			    int flags);
697a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic void FreeScreen(int scrnIndex, int flags);
707a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic void LeaveVT(int scrnIndex, int flags);
717a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
727a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskinstatic Bool ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
737a17889829b3f3655c47e2b01e282832fdb466d6Jeffrey Yasskin		       char **argv);
74static Bool PreInit(ScrnInfoPtr pScrn, int flags);
75
76typedef enum
77{
78    OPTION_SW_CURSOR,
79} modesettingOpts;
80
81static const OptionInfoRec Options[] = {
82    {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
83    {-1, NULL, OPTV_NONE, {0}, FALSE}
84};
85
86/*
87 * Functions that might be needed
88 */
89
90static const char *exaSymbols[] = {
91    "exaGetVersion",
92    "exaDriverInit",
93    "exaDriverFini",
94    "exaOffscreenAlloc",
95    "exaOffscreenFree",
96    "exaWaitSync",
97    NULL
98};
99
100static const char *fbSymbols[] = {
101    "fbPictureInit",
102    "fbScreenInit",
103    NULL
104};
105
106static const char *ddcSymbols[] = {
107    "xf86PrintEDID",
108    "xf86SetDDCproperties",
109    NULL
110};
111
112/*
113 * Exported Xorg driver functions to winsys
114 */
115
116void
117xorg_tracker_loader_ref_sym_lists()
118{
119    LoaderRefSymLists(exaSymbols, fbSymbols, ddcSymbols, NULL);
120}
121
122const OptionInfoRec *
123xorg_tracker_available_options(int chipid, int busid)
124{
125    return Options;
126}
127
128void
129xorg_tracker_set_functions(ScrnInfoPtr scrn)
130{
131    scrn->PreInit = PreInit;
132    scrn->ScreenInit = ScreenInit;
133    scrn->SwitchMode = SwitchMode;
134    scrn->AdjustFrame = AdjustFrame;
135    scrn->EnterVT = EnterVT;
136    scrn->LeaveVT = LeaveVT;
137    scrn->FreeScreen = FreeScreen;
138    scrn->ValidMode = ValidMode;
139}
140
141/*
142 * Static Xorg funtctions
143 */
144
145static Bool
146GetRec(ScrnInfoPtr pScrn)
147{
148    if (pScrn->driverPrivate)
149	return TRUE;
150
151    pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
152
153    return TRUE;
154}
155
156static void
157FreeRec(ScrnInfoPtr pScrn)
158{
159    if (!pScrn)
160	return;
161
162    if (!pScrn->driverPrivate)
163	return;
164
165    xfree(pScrn->driverPrivate);
166
167    pScrn->driverPrivate = NULL;
168}
169
170static void
171ProbeDDC(ScrnInfoPtr pScrn, int index)
172{
173    ConfiguredMonitor = NULL;
174}
175
176static Bool
177CreateFrontBuffer(ScrnInfoPtr pScrn)
178{
179    modesettingPtr ms = modesettingPTR(pScrn);
180    ScreenPtr pScreen = pScrn->pScreen;
181    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
182    unsigned handle, stride;
183
184    ms->noEvict = TRUE;
185    xorg_exa_set_displayed_usage(rootPixmap);
186    pScreen->ModifyPixmapHeader(rootPixmap,
187				pScrn->virtualX, pScrn->virtualY,
188				pScrn->depth, pScrn->bitsPerPixel,
189				pScrn->displayWidth * pScrn->bitsPerPixel / 8,
190				NULL);
191    ms->noEvict = FALSE;
192
193    handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
194
195    drmModeAddFB(ms->fd,
196		 pScrn->virtualX,
197		 pScrn->virtualY,
198		 pScrn->depth,
199		 pScrn->bitsPerPixel,
200		 stride,
201		 handle,
202		 &ms->fb_id);
203
204    pScrn->frameX0 = 0;
205    pScrn->frameY0 = 0;
206    AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
207
208    return TRUE;
209}
210
211static Bool
212crtc_resize(ScrnInfoPtr pScrn, int width, int height)
213{
214    modesettingPtr ms = modesettingPTR(pScrn);
215    //ScreenPtr pScreen = pScrn->pScreen;
216    //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
217    //Bool fbAccessDisabled;
218    //CARD8 *fbstart;
219
220    if (width == pScrn->virtualX && height == pScrn->virtualY)
221	return TRUE;
222
223    ErrorF("RESIZING TO %dx%d\n", width, height);
224
225    pScrn->virtualX = width;
226    pScrn->virtualY = height;
227
228    /* HW dependent - FIXME */
229    pScrn->displayWidth = pScrn->virtualX;
230
231    drmModeRmFB(ms->fd, ms->fb_id);
232
233    /* now create new frontbuffer */
234    return CreateFrontBuffer(pScrn);
235}
236
237static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
238    crtc_resize
239};
240
241static Bool
242PreInit(ScrnInfoPtr pScrn, int flags)
243{
244    xf86CrtcConfigPtr xf86_config;
245    modesettingPtr ms;
246    rgb defaultWeight = { 0, 0, 0 };
247    EntityInfoPtr pEnt;
248    EntPtr msEnt = NULL;
249    char *BusID;
250    int max_width, max_height;
251
252    if (pScrn->numEntities != 1)
253	return FALSE;
254
255    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
256
257    if (flags & PROBE_DETECT) {
258	ProbeDDC(pScrn, pEnt->index);
259	return TRUE;
260    }
261
262    /* Allocate driverPrivate */
263    if (!GetRec(pScrn))
264	return FALSE;
265
266    ms = modesettingPTR(pScrn);
267    ms->SaveGeneration = -1;
268    ms->pEnt = pEnt;
269
270    pScrn->displayWidth = 640;	       /* default it */
271
272    if (ms->pEnt->location.type != BUS_PCI)
273	return FALSE;
274
275    ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
276
277    /* Allocate an entity private if necessary */
278    if (xf86IsEntityShared(pScrn->entityList[0])) {
279	FatalError("Entity");
280#if 0
281	msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
282				     modesettingEntityIndex)->ptr;
283	ms->entityPrivate = msEnt;
284#else
285	(void)msEnt;
286#endif
287    } else
288	ms->entityPrivate = NULL;
289
290    if (xf86RegisterResources(ms->pEnt->index, NULL, ResNone)) {
291	return FALSE;
292    }
293
294    if (xf86IsEntityShared(pScrn->entityList[0])) {
295	if (xf86IsPrimInitDone(pScrn->entityList[0])) {
296	    /* do something */
297	} else {
298	    xf86SetPrimInitDone(pScrn->entityList[0]);
299	}
300    }
301
302    BusID = xalloc(64);
303    sprintf(BusID, "PCI:%d:%d:%d",
304	    ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
305	    ms->PciInfo->dev, ms->PciInfo->func
306	);
307
308    ms->api = drm_api_create();
309    ms->fd = drmOpen(NULL, BusID);
310
311    if (ms->fd < 0)
312	return FALSE;
313
314    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
315    pScrn->monitor = pScrn->confScreen->monitor;
316    pScrn->progClock = TRUE;
317    pScrn->rgbBits = 8;
318
319    if (!xf86SetDepthBpp
320	(pScrn, 0, 0, 0,
321	 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
322	return FALSE;
323
324    switch (pScrn->depth) {
325    case 15:
326    case 16:
327    case 24:
328	break;
329    default:
330	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
331		   "Given depth (%d) is not supported by the driver\n",
332		   pScrn->depth);
333	return FALSE;
334    }
335    xf86PrintDepthBpp(pScrn);
336
337    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
338	return FALSE;
339    if (!xf86SetDefaultVisual(pScrn, -1))
340	return FALSE;
341
342    /* Process the options */
343    xf86CollectOptions(pScrn, NULL);
344    if (!(ms->Options = xalloc(sizeof(Options))))
345	return FALSE;
346    memcpy(ms->Options, Options, sizeof(Options));
347    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
348
349    /* Allocate an xf86CrtcConfig */
350    xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
351    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
352
353    max_width = 8192;
354    max_height = 8192;
355    xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
356
357    if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
358	ms->SWCursor = TRUE;
359    }
360
361    SaveHWState(pScrn);
362
363    crtc_init(pScrn);
364    output_init(pScrn);
365
366    if (!xf86InitialConfiguration(pScrn, TRUE)) {
367	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
368	RestoreHWState(pScrn);
369	return FALSE;
370    }
371
372    RestoreHWState(pScrn);
373
374    /*
375     * If the driver can do gamma correction, it should call xf86SetGamma() here.
376     */
377    {
378	Gamma zeros = { 0.0, 0.0, 0.0 };
379
380	if (!xf86SetGamma(pScrn, zeros)) {
381	    return FALSE;
382	}
383    }
384
385    if (pScrn->modes == NULL) {
386	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
387	return FALSE;
388    }
389
390    pScrn->currentMode = pScrn->modes;
391
392    /* Set display resolution */
393    xf86SetDpi(pScrn, 0, 0);
394
395    /* Load the required sub modules */
396    if (!xf86LoadSubModule(pScrn, "fb")) {
397	return FALSE;
398    }
399
400    xf86LoaderReqSymLists(fbSymbols, NULL);
401
402    xf86LoadSubModule(pScrn, "exa");
403
404#ifdef DRI2
405    xf86LoadSubModule(pScrn, "dri2");
406#endif
407
408    return TRUE;
409}
410
411static Bool
412SaveHWState(ScrnInfoPtr pScrn)
413{
414    /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
415
416    return TRUE;
417}
418
419static Bool
420RestoreHWState(ScrnInfoPtr pScrn)
421{
422    /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
423
424    return TRUE;
425}
426
427static Bool
428CreateScreenResources(ScreenPtr pScreen)
429{
430    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
431    modesettingPtr ms = modesettingPTR(pScrn);
432    PixmapPtr rootPixmap;
433    Bool ret;
434    unsigned handle, stride;
435
436    ms->noEvict = TRUE;
437
438    pScreen->CreateScreenResources = ms->createScreenResources;
439    ret = pScreen->CreateScreenResources(pScreen);
440    pScreen->CreateScreenResources = CreateScreenResources;
441
442    rootPixmap = pScreen->GetScreenPixmap(pScreen);
443
444    xorg_exa_set_displayed_usage(rootPixmap);
445    if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
446	FatalError("Couldn't adjust screen pixmap\n");
447
448    ms->noEvict = FALSE;
449
450    handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
451
452    drmModeAddFB(ms->fd,
453		 pScrn->virtualX,
454		 pScrn->virtualY,
455		 pScrn->depth,
456		 pScrn->bitsPerPixel,
457		 stride,
458		 handle,
459                 &ms->fb_id);
460
461    AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
462
463    return ret;
464}
465
466static Bool
467ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
468{
469    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
470    modesettingPtr ms = modesettingPTR(pScrn);
471    VisualPtr visual;
472
473    /* deal with server regeneration */
474    if (ms->fd < 0) {
475	char *BusID;
476
477	BusID = xalloc(64);
478	sprintf(BusID, "PCI:%d:%d:%d",
479		((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
480		ms->PciInfo->dev, ms->PciInfo->func
481	    );
482
483	ms->fd = drmOpen(NULL, BusID);
484
485	if (ms->fd < 0)
486	    return FALSE;
487    }
488
489    if (!ms->screen) {
490	ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
491
492	if (!ms->screen) {
493	    FatalError("Could not init pipe_screen\n");
494	    return FALSE;
495	}
496    }
497
498    pScrn->pScreen = pScreen;
499
500    /* HW dependent - FIXME */
501    pScrn->displayWidth = pScrn->virtualX;
502
503    miClearVisualTypes();
504
505    if (!miSetVisualTypes(pScrn->depth,
506			  miGetDefaultVisualMask(pScrn->depth),
507			  pScrn->rgbBits, pScrn->defaultVisual))
508	return FALSE;
509
510    if (!miSetPixmapDepths())
511	return FALSE;
512
513    pScrn->memPhysBase = 0;
514    pScrn->fbOffset = 0;
515
516    if (!fbScreenInit(pScreen, NULL,
517		      pScrn->virtualX, pScrn->virtualY,
518		      pScrn->xDpi, pScrn->yDpi,
519		      pScrn->displayWidth, pScrn->bitsPerPixel))
520	return FALSE;
521
522    if (pScrn->bitsPerPixel > 8) {
523	/* Fixup RGB ordering */
524	visual = pScreen->visuals + pScreen->numVisuals;
525	while (--visual >= pScreen->visuals) {
526	    if ((visual->class | DynamicClass) == DirectColor) {
527		visual->offsetRed = pScrn->offset.red;
528		visual->offsetGreen = pScrn->offset.green;
529		visual->offsetBlue = pScrn->offset.blue;
530		visual->redMask = pScrn->mask.red;
531		visual->greenMask = pScrn->mask.green;
532		visual->blueMask = pScrn->mask.blue;
533	    }
534	}
535    }
536
537    fbPictureInit(pScreen, NULL, 0);
538
539    ms->createScreenResources = pScreen->CreateScreenResources;
540    pScreen->CreateScreenResources = CreateScreenResources;
541
542    xf86SetBlackWhitePixels(pScreen);
543
544    ms->exa = xorg_exa_init(pScrn);
545
546    miInitializeBackingStore(pScreen);
547    xf86SetBackingStore(pScreen);
548    xf86SetSilkenMouse(pScreen);
549    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
550
551    /* Need to extend HWcursor support to handle mask interleave */
552    if (!ms->SWCursor)
553	xf86_cursors_init(pScreen, 64, 64,
554			  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
555			  HARDWARE_CURSOR_ARGB);
556
557    /* Must force it before EnterVT, so we are in control of VT and
558     * later memory should be bound when allocating, e.g rotate_mem */
559    pScrn->vtSema = TRUE;
560
561    pScreen->SaveScreen = xf86SaveScreen;
562    ms->CloseScreen = pScreen->CloseScreen;
563    pScreen->CloseScreen = CloseScreen;
564
565    if (!xf86CrtcScreenInit(pScreen))
566	return FALSE;
567
568    if (!miCreateDefColormap(pScreen))
569	return FALSE;
570
571    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
572
573    if (serverGeneration == 1)
574	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
575
576#if 1
577#ifdef DRI2
578    driScreenInit(pScreen);
579#endif
580#endif
581
582    return EnterVT(scrnIndex, 1);
583}
584
585static void
586AdjustFrame(int scrnIndex, int x, int y, int flags)
587{
588    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
589    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
590    xf86OutputPtr output = config->output[config->compat_output];
591    xf86CrtcPtr crtc = output->crtc;
592
593    if (crtc && crtc->enabled) {
594	crtc->funcs->mode_set(crtc, pScrn->currentMode, pScrn->currentMode, x,
595			      y);
596	crtc->x = output->initial_x + x;
597	crtc->y = output->initial_y + y;
598    }
599}
600
601static void
602FreeScreen(int scrnIndex, int flags)
603{
604    FreeRec(xf86Screens[scrnIndex]);
605}
606
607/* HACK */
608void
609cursor_destroy(xf86CrtcPtr crtc);
610
611static void
612LeaveVT(int scrnIndex, int flags)
613{
614    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
615    modesettingPtr ms = modesettingPTR(pScrn);
616    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
617    int o;
618
619    for (o = 0; o < config->num_crtc; o++) {
620	xf86CrtcPtr crtc = config->crtc[o];
621
622	cursor_destroy(crtc);
623
624	if (crtc->rotatedPixmap || crtc->rotatedData) {
625	    crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
626					crtc->rotatedData);
627	    crtc->rotatedPixmap = NULL;
628	    crtc->rotatedData = NULL;
629	}
630    }
631
632    drmModeRmFB(ms->fd, ms->fb_id);
633
634    RestoreHWState(pScrn);
635
636    pScrn->vtSema = FALSE;
637}
638
639/*
640 * This gets called when gaining control of the VT, and from ScreenInit().
641 */
642static Bool
643EnterVT(int scrnIndex, int flags)
644{
645    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
646    modesettingPtr ms = modesettingPTR(pScrn);
647
648    /*
649     * Only save state once per server generation since that's what most
650     * drivers do.  Could change this to save state at each VT enter.
651     */
652    if (ms->SaveGeneration != serverGeneration) {
653	ms->SaveGeneration = serverGeneration;
654	SaveHWState(pScrn);
655    }
656
657    if (!flags)			       /* signals startup as we'll do this in CreateScreenResources */
658	CreateFrontBuffer(pScrn);
659
660    if (!xf86SetDesiredModes(pScrn))
661	return FALSE;
662
663    return TRUE;
664}
665
666static Bool
667SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
668{
669    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
670
671    return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
672}
673
674static Bool
675CloseScreen(int scrnIndex, ScreenPtr pScreen)
676{
677    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
678    modesettingPtr ms = modesettingPTR(pScrn);
679
680    if (pScrn->vtSema) {
681	LeaveVT(scrnIndex, 0);
682    }
683#ifdef DRI2
684    driCloseScreen(pScreen);
685#endif
686
687    pScreen->CreateScreenResources = ms->createScreenResources;
688
689    if (ms->exa)
690	xorg_exa_close(pScrn);
691
692	ms->api->destroy(ms->api);
693	ms->api = NULL;
694    drmClose(ms->fd);
695    ms->fd = -1;
696
697    pScrn->vtSema = FALSE;
698    pScreen->CloseScreen = ms->CloseScreen;
699    return (*pScreen->CloseScreen) (scrnIndex, pScreen);
700}
701
702static ModeStatus
703ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
704{
705    return MODE_OK;
706}
707
708/* vim: set sw=4 ts=8 sts=4: */
709