2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
32 #include "xorg-server.h"
34 #include "xf86_OSproc.h"
37 #include "xf86PciInfo.h"
39 #include "xf86Resources.h"
40 #include "mipointer.h"
42 #include <X11/extensions/randr.h>
47 #include "miscstruct.h"
48 #include "dixstruct.h"
50 #include <X11/extensions/Xv.h>
51 #ifndef XSERVER_LIBPCIACCESS
52 #error "libpciaccess needed"
55 #include <pciaccess.h>
57 #include "xorg_tracker.h"
58 #include "xorg_winsys.h"
60 static void AdjustFrame(int scrnIndex
, int x
, int y
, int flags
);
61 static Bool
CloseScreen(int scrnIndex
, ScreenPtr pScreen
);
62 static Bool
EnterVT(int scrnIndex
, int flags
);
63 static Bool
SaveHWState(ScrnInfoPtr pScrn
);
64 static Bool
RestoreHWState(ScrnInfoPtr pScrn
);
67 static ModeStatus
ValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
,
69 static void FreeScreen(int scrnIndex
, int flags
);
70 static void LeaveVT(int scrnIndex
, int flags
);
71 static Bool
SwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
);
72 static Bool
ScreenInit(int scrnIndex
, ScreenPtr pScreen
, int argc
,
74 static Bool
PreInit(ScrnInfoPtr pScrn
, int flags
);
81 static const OptionInfoRec Options
[] = {
82 {OPTION_SW_CURSOR
, "SWcursor", OPTV_BOOLEAN
, {0}, FALSE
},
83 {-1, NULL
, OPTV_NONE
, {0}, FALSE
}
87 * Functions that might be needed
90 static const char *exaSymbols
[] = {
100 static const char *fbSymbols
[] = {
106 static const char *ddcSymbols
[] = {
108 "xf86SetDDCproperties",
113 * Exported Xorg driver functions to winsys
117 xorg_tracker_loader_ref_sym_lists()
119 LoaderRefSymLists(exaSymbols
, fbSymbols
, ddcSymbols
, NULL
);
122 const OptionInfoRec
*
123 xorg_tracker_available_options(int chipid
, int busid
)
129 xorg_tracker_set_functions(ScrnInfoPtr scrn
)
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
;
142 * Static Xorg funtctions
146 GetRec(ScrnInfoPtr pScrn
)
148 if (pScrn
->driverPrivate
)
151 pScrn
->driverPrivate
= xnfcalloc(sizeof(modesettingRec
), 1);
157 FreeRec(ScrnInfoPtr pScrn
)
162 if (!pScrn
->driverPrivate
)
165 xfree(pScrn
->driverPrivate
);
167 pScrn
->driverPrivate
= NULL
;
171 ProbeDDC(ScrnInfoPtr pScrn
, int index
)
173 ConfiguredMonitor
= NULL
;
177 CreateFrontBuffer(ScrnInfoPtr pScrn
)
179 modesettingPtr ms
= modesettingPTR(pScrn
);
180 ScreenPtr pScreen
= pScrn
->pScreen
;
181 PixmapPtr rootPixmap
= pScreen
->GetScreenPixmap(pScreen
);
182 unsigned handle
, stride
;
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,
193 handle
= xorg_exa_get_pixmap_handle(rootPixmap
, &stride
);
206 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
212 crtc_resize(ScrnInfoPtr pScrn
, int width
, int height
)
214 modesettingPtr ms
= modesettingPTR(pScrn
);
215 //ScreenPtr pScreen = pScrn->pScreen;
216 //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
217 //Bool fbAccessDisabled;
220 if (width
== pScrn
->virtualX
&& height
== pScrn
->virtualY
)
223 ErrorF("RESIZING TO %dx%d\n", width
, height
);
225 pScrn
->virtualX
= width
;
226 pScrn
->virtualY
= height
;
228 /* HW dependent - FIXME */
229 pScrn
->displayWidth
= pScrn
->virtualX
;
231 drmModeRmFB(ms
->fd
, ms
->fb_id
);
233 /* now create new frontbuffer */
234 return CreateFrontBuffer(pScrn
);
237 static const xf86CrtcConfigFuncsRec crtc_config_funcs
= {
242 PreInit(ScrnInfoPtr pScrn
, int flags
)
244 xf86CrtcConfigPtr xf86_config
;
246 rgb defaultWeight
= { 0, 0, 0 };
250 int max_width
, max_height
;
252 if (pScrn
->numEntities
!= 1)
255 pEnt
= xf86GetEntityInfo(pScrn
->entityList
[0]);
257 if (flags
& PROBE_DETECT
) {
258 ProbeDDC(pScrn
, pEnt
->index
);
262 /* Allocate driverPrivate */
266 ms
= modesettingPTR(pScrn
);
267 ms
->SaveGeneration
= -1;
270 pScrn
->displayWidth
= 640; /* default it */
272 if (ms
->pEnt
->location
.type
!= BUS_PCI
)
275 ms
->PciInfo
= xf86GetPciInfoForEntity(ms
->pEnt
->index
);
277 /* Allocate an entity private if necessary */
278 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
279 FatalError("Entity");
281 msEnt
= xf86GetEntityPrivate(pScrn
->entityList
[0],
282 modesettingEntityIndex
)->ptr
;
283 ms
->entityPrivate
= msEnt
;
288 ms
->entityPrivate
= NULL
;
290 if (xf86RegisterResources(ms
->pEnt
->index
, NULL
, ResNone
)) {
294 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
295 if (xf86IsPrimInitDone(pScrn
->entityList
[0])) {
298 xf86SetPrimInitDone(pScrn
->entityList
[0]);
303 sprintf(BusID
, "PCI:%d:%d:%d",
304 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
305 ms
->PciInfo
->dev
, ms
->PciInfo
->func
308 ms
->api
= drm_api_create();
309 ms
->fd
= drmOpen(NULL
, BusID
);
314 pScrn
->racMemFlags
= RAC_FB
| RAC_COLORMAP
;
315 pScrn
->monitor
= pScrn
->confScreen
->monitor
;
316 pScrn
->progClock
= TRUE
;
321 PreferConvert24to32
| SupportConvert24to32
| Support32bppFb
))
324 switch (pScrn
->depth
) {
330 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
331 "Given depth (%d) is not supported by the driver\n",
335 xf86PrintDepthBpp(pScrn
);
337 if (!xf86SetWeight(pScrn
, defaultWeight
, defaultWeight
))
339 if (!xf86SetDefaultVisual(pScrn
, -1))
342 /* Process the options */
343 xf86CollectOptions(pScrn
, NULL
);
344 if (!(ms
->Options
= xalloc(sizeof(Options
))))
346 memcpy(ms
->Options
, Options
, sizeof(Options
));
347 xf86ProcessOptions(pScrn
->scrnIndex
, pScrn
->options
, ms
->Options
);
349 /* Allocate an xf86CrtcConfig */
350 xf86CrtcConfigInit(pScrn
, &crtc_config_funcs
);
351 xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
355 xf86CrtcSetSizeRange(pScrn
, 320, 200, max_width
, max_height
);
357 if (xf86ReturnOptValBool(ms
->Options
, OPTION_SW_CURSOR
, FALSE
)) {
366 if (!xf86InitialConfiguration(pScrn
, TRUE
)) {
367 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No valid modes.\n");
368 RestoreHWState(pScrn
);
372 RestoreHWState(pScrn
);
375 * If the driver can do gamma correction, it should call xf86SetGamma() here.
378 Gamma zeros
= { 0.0, 0.0, 0.0 };
380 if (!xf86SetGamma(pScrn
, zeros
)) {
385 if (pScrn
->modes
== NULL
) {
386 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No modes.\n");
390 pScrn
->currentMode
= pScrn
->modes
;
392 /* Set display resolution */
393 xf86SetDpi(pScrn
, 0, 0);
395 /* Load the required sub modules */
396 if (!xf86LoadSubModule(pScrn
, "fb")) {
400 xf86LoaderReqSymLists(fbSymbols
, NULL
);
402 xf86LoadSubModule(pScrn
, "exa");
405 xf86LoadSubModule(pScrn
, "dri2");
412 SaveHWState(ScrnInfoPtr pScrn
)
414 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
420 RestoreHWState(ScrnInfoPtr pScrn
)
422 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
428 CreateScreenResources(ScreenPtr pScreen
)
430 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
431 modesettingPtr ms
= modesettingPTR(pScrn
);
432 PixmapPtr rootPixmap
;
434 unsigned handle
, stride
;
438 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
439 ret
= pScreen
->CreateScreenResources(pScreen
);
440 pScreen
->CreateScreenResources
= CreateScreenResources
;
442 rootPixmap
= pScreen
->GetScreenPixmap(pScreen
);
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");
450 handle
= xorg_exa_get_pixmap_handle(rootPixmap
, &stride
);
461 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
467 ScreenInit(int scrnIndex
, ScreenPtr pScreen
, int argc
, char **argv
)
469 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
470 modesettingPtr ms
= modesettingPTR(pScrn
);
473 /* deal with server regeneration */
478 sprintf(BusID
, "PCI:%d:%d:%d",
479 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
480 ms
->PciInfo
->dev
, ms
->PciInfo
->func
483 ms
->fd
= drmOpen(NULL
, BusID
);
490 ms
->screen
= ms
->api
->create_screen(ms
->api
, ms
->fd
, NULL
);
493 FatalError("Could not init pipe_screen\n");
498 pScrn
->pScreen
= pScreen
;
500 /* HW dependent - FIXME */
501 pScrn
->displayWidth
= pScrn
->virtualX
;
503 miClearVisualTypes();
505 if (!miSetVisualTypes(pScrn
->depth
,
506 miGetDefaultVisualMask(pScrn
->depth
),
507 pScrn
->rgbBits
, pScrn
->defaultVisual
))
510 if (!miSetPixmapDepths())
513 pScrn
->memPhysBase
= 0;
516 if (!fbScreenInit(pScreen
, NULL
,
517 pScrn
->virtualX
, pScrn
->virtualY
,
518 pScrn
->xDpi
, pScrn
->yDpi
,
519 pScrn
->displayWidth
, pScrn
->bitsPerPixel
))
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
;
537 fbPictureInit(pScreen
, NULL
, 0);
539 ms
->createScreenResources
= pScreen
->CreateScreenResources
;
540 pScreen
->CreateScreenResources
= CreateScreenResources
;
542 xf86SetBlackWhitePixels(pScreen
);
544 ms
->exa
= xorg_exa_init(pScrn
);
546 miInitializeBackingStore(pScreen
);
547 xf86SetBackingStore(pScreen
);
548 xf86SetSilkenMouse(pScreen
);
549 miDCInitialize(pScreen
, xf86GetPointerScreenFuncs());
551 /* Need to extend HWcursor support to handle mask interleave */
553 xf86_cursors_init(pScreen
, 64, 64,
554 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
|
555 HARDWARE_CURSOR_ARGB
);
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
;
561 pScreen
->SaveScreen
= xf86SaveScreen
;
562 ms
->CloseScreen
= pScreen
->CloseScreen
;
563 pScreen
->CloseScreen
= CloseScreen
;
565 if (!xf86CrtcScreenInit(pScreen
))
568 if (!miCreateDefColormap(pScreen
))
571 xf86DPMSInit(pScreen
, xf86DPMSSet
, 0);
573 if (serverGeneration
== 1)
574 xf86ShowUnusedOptions(pScrn
->scrnIndex
, pScrn
->options
);
578 driScreenInit(pScreen
);
582 return EnterVT(scrnIndex
, 1);
586 AdjustFrame(int scrnIndex
, int x
, int y
, int flags
)
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
;
593 if (crtc
&& crtc
->enabled
) {
594 crtc
->funcs
->mode_set(crtc
, pScrn
->currentMode
, pScrn
->currentMode
, x
,
596 crtc
->x
= output
->initial_x
+ x
;
597 crtc
->y
= output
->initial_y
+ y
;
602 FreeScreen(int scrnIndex
, int flags
)
604 FreeRec(xf86Screens
[scrnIndex
]);
609 cursor_destroy(xf86CrtcPtr crtc
);
612 LeaveVT(int scrnIndex
, int flags
)
614 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
615 modesettingPtr ms
= modesettingPTR(pScrn
);
616 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
619 for (o
= 0; o
< config
->num_crtc
; o
++) {
620 xf86CrtcPtr crtc
= config
->crtc
[o
];
622 cursor_destroy(crtc
);
624 if (crtc
->rotatedPixmap
|| crtc
->rotatedData
) {
625 crtc
->funcs
->shadow_destroy(crtc
, crtc
->rotatedPixmap
,
627 crtc
->rotatedPixmap
= NULL
;
628 crtc
->rotatedData
= NULL
;
632 drmModeRmFB(ms
->fd
, ms
->fb_id
);
634 RestoreHWState(pScrn
);
636 if (drmDropMaster(ms
->fd
))
637 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
638 "drmDropMaster failed: %s\n", strerror(errno
));
640 pScrn
->vtSema
= FALSE
;
644 * This gets called when gaining control of the VT, and from ScreenInit().
647 EnterVT(int scrnIndex
, int flags
)
649 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
650 modesettingPtr ms
= modesettingPTR(pScrn
);
652 if (drmSetMaster(ms
->fd
)) {
653 if (errno
== EINVAL
) {
654 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
655 "drmSetMaster failed: 2.6.29 or newer kernel required for "
656 "multi-server DRI\n");
658 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
659 "drmSetMaster failed: %s\n", strerror(errno
));
664 * Only save state once per server generation since that's what most
665 * drivers do. Could change this to save state at each VT enter.
667 if (ms
->SaveGeneration
!= serverGeneration
) {
668 ms
->SaveGeneration
= serverGeneration
;
672 if (!flags
) /* signals startup as we'll do this in CreateScreenResources */
673 CreateFrontBuffer(pScrn
);
675 if (!xf86SetDesiredModes(pScrn
))
682 SwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
)
684 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
686 return xf86SetSingleMode(pScrn
, mode
, RR_Rotate_0
);
690 CloseScreen(int scrnIndex
, ScreenPtr pScreen
)
692 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
693 modesettingPtr ms
= modesettingPTR(pScrn
);
696 LeaveVT(scrnIndex
, 0);
699 driCloseScreen(pScreen
);
702 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
705 xorg_exa_close(pScrn
);
707 ms
->api
->destroy(ms
->api
);
712 pScrn
->vtSema
= FALSE
;
713 pScreen
->CloseScreen
= ms
->CloseScreen
;
714 return (*pScreen
->CloseScreen
) (scrnIndex
, pScreen
);
718 ValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
, int flags
)
723 /* vim: set sw=4 ts=8 sts=4: */