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
);
184 pScreen
->ModifyPixmapHeader(rootPixmap
,
185 pScrn
->virtualX
, pScrn
->virtualY
,
186 pScrn
->depth
, pScrn
->bitsPerPixel
,
187 pScrn
->displayWidth
* pScrn
->bitsPerPixel
/ 8,
196 pScrn
->displayWidth
* pScrn
->bitsPerPixel
/ 8,
197 xorg_exa_get_pixmap_handle(rootPixmap
), &ms
->fb_id
);
201 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
207 crtc_resize(ScrnInfoPtr pScrn
, int width
, int height
)
209 modesettingPtr ms
= modesettingPTR(pScrn
);
210 //ScreenPtr pScreen = pScrn->pScreen;
211 //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
212 //Bool fbAccessDisabled;
215 if (width
== pScrn
->virtualX
&& height
== pScrn
->virtualY
)
218 ErrorF("RESIZING TO %dx%d\n", width
, height
);
220 pScrn
->virtualX
= width
;
221 pScrn
->virtualY
= height
;
223 /* HW dependent - FIXME */
224 pScrn
->displayWidth
= pScrn
->virtualX
;
226 drmModeRmFB(ms
->fd
, ms
->fb_id
);
228 /* now create new frontbuffer */
229 return CreateFrontBuffer(pScrn
);
232 static const xf86CrtcConfigFuncsRec crtc_config_funcs
= {
237 PreInit(ScrnInfoPtr pScrn
, int flags
)
239 xf86CrtcConfigPtr xf86_config
;
241 rgb defaultWeight
= { 0, 0, 0 };
245 int max_width
, max_height
;
247 if (pScrn
->numEntities
!= 1)
250 pEnt
= xf86GetEntityInfo(pScrn
->entityList
[0]);
252 if (flags
& PROBE_DETECT
) {
253 ProbeDDC(pScrn
, pEnt
->index
);
257 /* Allocate driverPrivate */
261 ms
= modesettingPTR(pScrn
);
262 ms
->SaveGeneration
= -1;
265 pScrn
->displayWidth
= 640; /* default it */
267 if (ms
->pEnt
->location
.type
!= BUS_PCI
)
270 ms
->PciInfo
= xf86GetPciInfoForEntity(ms
->pEnt
->index
);
272 /* Allocate an entity private if necessary */
273 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
274 FatalError("Entity");
276 msEnt
= xf86GetEntityPrivate(pScrn
->entityList
[0],
277 modesettingEntityIndex
)->ptr
;
278 ms
->entityPrivate
= msEnt
;
283 ms
->entityPrivate
= NULL
;
285 if (xf86RegisterResources(ms
->pEnt
->index
, NULL
, ResNone
)) {
289 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
290 if (xf86IsPrimInitDone(pScrn
->entityList
[0])) {
293 xf86SetPrimInitDone(pScrn
->entityList
[0]);
298 sprintf(BusID
, "PCI:%d:%d:%d",
299 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
300 ms
->PciInfo
->dev
, ms
->PciInfo
->func
303 ms
->api
= drm_api_create();
304 ms
->fd
= drmOpen(NULL
, BusID
);
309 pScrn
->racMemFlags
= RAC_FB
| RAC_COLORMAP
;
310 pScrn
->monitor
= pScrn
->confScreen
->monitor
;
311 pScrn
->progClock
= TRUE
;
316 PreferConvert24to32
| SupportConvert24to32
| Support32bppFb
))
319 switch (pScrn
->depth
) {
325 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
326 "Given depth (%d) is not supported by the driver\n",
330 xf86PrintDepthBpp(pScrn
);
332 if (!xf86SetWeight(pScrn
, defaultWeight
, defaultWeight
))
334 if (!xf86SetDefaultVisual(pScrn
, -1))
337 /* Process the options */
338 xf86CollectOptions(pScrn
, NULL
);
339 if (!(ms
->Options
= xalloc(sizeof(Options
))))
341 memcpy(ms
->Options
, Options
, sizeof(Options
));
342 xf86ProcessOptions(pScrn
->scrnIndex
, pScrn
->options
, ms
->Options
);
344 /* Allocate an xf86CrtcConfig */
345 xf86CrtcConfigInit(pScrn
, &crtc_config_funcs
);
346 xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
350 xf86CrtcSetSizeRange(pScrn
, 320, 200, max_width
, max_height
);
352 if (xf86ReturnOptValBool(ms
->Options
, OPTION_SW_CURSOR
, FALSE
)) {
361 if (!xf86InitialConfiguration(pScrn
, TRUE
)) {
362 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No valid modes.\n");
363 RestoreHWState(pScrn
);
367 RestoreHWState(pScrn
);
370 * If the driver can do gamma correction, it should call xf86SetGamma() here.
373 Gamma zeros
= { 0.0, 0.0, 0.0 };
375 if (!xf86SetGamma(pScrn
, zeros
)) {
380 if (pScrn
->modes
== NULL
) {
381 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No modes.\n");
385 pScrn
->currentMode
= pScrn
->modes
;
387 /* Set display resolution */
388 xf86SetDpi(pScrn
, 0, 0);
390 /* Load the required sub modules */
391 if (!xf86LoadSubModule(pScrn
, "fb")) {
395 xf86LoaderReqSymLists(fbSymbols
, NULL
);
397 xf86LoadSubModule(pScrn
, "exa");
400 xf86LoadSubModule(pScrn
, "dri2");
407 SaveHWState(ScrnInfoPtr pScrn
)
409 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
415 RestoreHWState(ScrnInfoPtr pScrn
)
417 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
423 CreateScreenResources(ScreenPtr pScreen
)
425 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
426 modesettingPtr ms
= modesettingPTR(pScrn
);
427 PixmapPtr rootPixmap
;
432 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
433 ret
= pScreen
->CreateScreenResources(pScreen
);
434 pScreen
->CreateScreenResources
= CreateScreenResources
;
436 rootPixmap
= pScreen
->GetScreenPixmap(pScreen
);
438 if (!pScreen
->ModifyPixmapHeader(rootPixmap
, -1, -1, -1, -1, -1, NULL
))
439 FatalError("Couldn't adjust screen pixmap\n");
448 pScrn
->displayWidth
* pScrn
->bitsPerPixel
/ 8,
449 xorg_exa_get_pixmap_handle(rootPixmap
), &ms
->fb_id
);
451 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
457 ScreenInit(int scrnIndex
, ScreenPtr pScreen
, int argc
, char **argv
)
459 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
460 modesettingPtr ms
= modesettingPTR(pScrn
);
463 /* deal with server regeneration */
468 sprintf(BusID
, "PCI:%d:%d:%d",
469 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
470 ms
->PciInfo
->dev
, ms
->PciInfo
->func
473 ms
->fd
= drmOpen(NULL
, BusID
);
480 ms
->screen
= ms
->api
->create_screen(ms
->api
, ms
->fd
, NULL
);
483 FatalError("Could not init pipe_screen\n");
488 pScrn
->pScreen
= pScreen
;
490 /* HW dependent - FIXME */
491 pScrn
->displayWidth
= pScrn
->virtualX
;
493 miClearVisualTypes();
495 if (!miSetVisualTypes(pScrn
->depth
,
496 miGetDefaultVisualMask(pScrn
->depth
),
497 pScrn
->rgbBits
, pScrn
->defaultVisual
))
500 if (!miSetPixmapDepths())
503 pScrn
->memPhysBase
= 0;
506 if (!fbScreenInit(pScreen
, NULL
,
507 pScrn
->virtualX
, pScrn
->virtualY
,
508 pScrn
->xDpi
, pScrn
->yDpi
,
509 pScrn
->displayWidth
, pScrn
->bitsPerPixel
))
512 if (pScrn
->bitsPerPixel
> 8) {
513 /* Fixup RGB ordering */
514 visual
= pScreen
->visuals
+ pScreen
->numVisuals
;
515 while (--visual
>= pScreen
->visuals
) {
516 if ((visual
->class | DynamicClass
) == DirectColor
) {
517 visual
->offsetRed
= pScrn
->offset
.red
;
518 visual
->offsetGreen
= pScrn
->offset
.green
;
519 visual
->offsetBlue
= pScrn
->offset
.blue
;
520 visual
->redMask
= pScrn
->mask
.red
;
521 visual
->greenMask
= pScrn
->mask
.green
;
522 visual
->blueMask
= pScrn
->mask
.blue
;
527 fbPictureInit(pScreen
, NULL
, 0);
529 ms
->createScreenResources
= pScreen
->CreateScreenResources
;
530 pScreen
->CreateScreenResources
= CreateScreenResources
;
532 xf86SetBlackWhitePixels(pScreen
);
534 ms
->exa
= xorg_exa_init(pScrn
);
536 miInitializeBackingStore(pScreen
);
537 xf86SetBackingStore(pScreen
);
538 xf86SetSilkenMouse(pScreen
);
539 miDCInitialize(pScreen
, xf86GetPointerScreenFuncs());
541 /* Need to extend HWcursor support to handle mask interleave */
543 xf86_cursors_init(pScreen
, 64, 64,
544 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
|
545 HARDWARE_CURSOR_ARGB
);
547 /* Must force it before EnterVT, so we are in control of VT and
548 * later memory should be bound when allocating, e.g rotate_mem */
549 pScrn
->vtSema
= TRUE
;
551 pScreen
->SaveScreen
= xf86SaveScreen
;
552 ms
->CloseScreen
= pScreen
->CloseScreen
;
553 pScreen
->CloseScreen
= CloseScreen
;
555 if (!xf86CrtcScreenInit(pScreen
))
558 if (!miCreateDefColormap(pScreen
))
561 xf86DPMSInit(pScreen
, xf86DPMSSet
, 0);
563 if (serverGeneration
== 1)
564 xf86ShowUnusedOptions(pScrn
->scrnIndex
, pScrn
->options
);
568 driScreenInit(pScreen
);
572 return EnterVT(scrnIndex
, 1);
576 AdjustFrame(int scrnIndex
, int x
, int y
, int flags
)
578 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
579 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
580 xf86OutputPtr output
= config
->output
[config
->compat_output
];
581 xf86CrtcPtr crtc
= output
->crtc
;
583 if (crtc
&& crtc
->enabled
) {
584 crtc
->funcs
->mode_set(crtc
, pScrn
->currentMode
, pScrn
->currentMode
, x
,
586 crtc
->x
= output
->initial_x
+ x
;
587 crtc
->y
= output
->initial_y
+ y
;
592 FreeScreen(int scrnIndex
, int flags
)
594 FreeRec(xf86Screens
[scrnIndex
]);
599 cursor_destroy(xf86CrtcPtr crtc
);
602 LeaveVT(int scrnIndex
, int flags
)
604 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
605 modesettingPtr ms
= modesettingPTR(pScrn
);
606 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
609 for (o
= 0; o
< config
->num_crtc
; o
++) {
610 xf86CrtcPtr crtc
= config
->crtc
[o
];
612 cursor_destroy(crtc
);
614 if (crtc
->rotatedPixmap
|| crtc
->rotatedData
) {
615 crtc
->funcs
->shadow_destroy(crtc
, crtc
->rotatedPixmap
,
617 crtc
->rotatedPixmap
= NULL
;
618 crtc
->rotatedData
= NULL
;
622 drmModeRmFB(ms
->fd
, ms
->fb_id
);
624 RestoreHWState(pScrn
);
626 pScrn
->vtSema
= FALSE
;
630 * This gets called when gaining control of the VT, and from ScreenInit().
633 EnterVT(int scrnIndex
, int flags
)
635 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
636 modesettingPtr ms
= modesettingPTR(pScrn
);
639 * Only save state once per server generation since that's what most
640 * drivers do. Could change this to save state at each VT enter.
642 if (ms
->SaveGeneration
!= serverGeneration
) {
643 ms
->SaveGeneration
= serverGeneration
;
647 if (!flags
) /* signals startup as we'll do this in CreateScreenResources */
648 CreateFrontBuffer(pScrn
);
650 if (!xf86SetDesiredModes(pScrn
))
657 SwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
)
659 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
661 return xf86SetSingleMode(pScrn
, mode
, RR_Rotate_0
);
665 CloseScreen(int scrnIndex
, ScreenPtr pScreen
)
667 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
668 modesettingPtr ms
= modesettingPTR(pScrn
);
671 LeaveVT(scrnIndex
, 0);
674 driCloseScreen(pScreen
);
677 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
680 xorg_exa_close(pScrn
);
682 ms
->api
->destroy(ms
->api
);
687 pScrn
->vtSema
= FALSE
;
688 pScreen
->CloseScreen
= ms
->CloseScreen
;
689 return (*pScreen
->CloseScreen
) (scrnIndex
, pScreen
);
693 ValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
, int flags
)
698 /* vim: set sw=4 ts=8 sts=4: */