Merge commit 'origin/openvg-1.0'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_driver.c
1 /*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
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:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
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.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31
32 #include "xorg-server.h"
33 #include "xf86.h"
34 #include "xf86_OSproc.h"
35 #include "compiler.h"
36 #include "xf86RAC.h"
37 #include "xf86PciInfo.h"
38 #include "xf86Pci.h"
39 #include "xf86Resources.h"
40 #include "mipointer.h"
41 #include "micmap.h"
42 #include <X11/extensions/randr.h>
43 #include "fb.h"
44 #include "edid.h"
45 #include "xf86i2c.h"
46 #include "xf86Crtc.h"
47 #include "miscstruct.h"
48 #include "dixstruct.h"
49 #include "xf86xv.h"
50 #include <X11/extensions/Xv.h>
51 #ifndef XSERVER_LIBPCIACCESS
52 #error "libpciaccess needed"
53 #endif
54
55 #include <pciaccess.h>
56
57 #include "xorg_tracker.h"
58 #include "xorg_winsys.h"
59
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);
65
66
67 static ModeStatus ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
68 int flags);
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,
73 char **argv);
74 static Bool PreInit(ScrnInfoPtr pScrn, int flags);
75
76 typedef enum
77 {
78 OPTION_SW_CURSOR,
79 } modesettingOpts;
80
81 static 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
90 static const char *exaSymbols[] = {
91 "exaGetVersion",
92 "exaDriverInit",
93 "exaDriverFini",
94 "exaOffscreenAlloc",
95 "exaOffscreenFree",
96 "exaWaitSync",
97 NULL
98 };
99
100 static const char *fbSymbols[] = {
101 "fbPictureInit",
102 "fbScreenInit",
103 NULL
104 };
105
106 static const char *ddcSymbols[] = {
107 "xf86PrintEDID",
108 "xf86SetDDCproperties",
109 NULL
110 };
111
112 /*
113 * Exported Xorg driver functions to winsys
114 */
115
116 void
117 xorg_tracker_loader_ref_sym_lists()
118 {
119 LoaderRefSymLists(exaSymbols, fbSymbols, ddcSymbols, NULL);
120 }
121
122 const OptionInfoRec *
123 xorg_tracker_available_options(int chipid, int busid)
124 {
125 return Options;
126 }
127
128 void
129 xorg_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
145 static Bool
146 GetRec(ScrnInfoPtr pScrn)
147 {
148 if (pScrn->driverPrivate)
149 return TRUE;
150
151 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
152
153 return TRUE;
154 }
155
156 static void
157 FreeRec(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
170 static void
171 ProbeDDC(ScrnInfoPtr pScrn, int index)
172 {
173 ConfiguredMonitor = NULL;
174 }
175
176 static Bool
177 CreateFrontBuffer(ScrnInfoPtr pScrn)
178 {
179 modesettingPtr ms = modesettingPTR(pScrn);
180 ScreenPtr pScreen = pScrn->pScreen;
181 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
182
183 ms->noEvict = TRUE;
184 pScreen->ModifyPixmapHeader(rootPixmap,
185 pScrn->virtualX, pScrn->virtualY,
186 pScrn->depth, pScrn->bitsPerPixel,
187 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
188 NULL);
189 ms->noEvict = FALSE;
190
191 drmModeAddFB(ms->fd,
192 pScrn->virtualX,
193 pScrn->virtualY,
194 pScrn->depth,
195 pScrn->bitsPerPixel,
196 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
197 xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
198
199 pScrn->frameX0 = 0;
200 pScrn->frameY0 = 0;
201 AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
202
203 return TRUE;
204 }
205
206 static Bool
207 crtc_resize(ScrnInfoPtr pScrn, int width, int height)
208 {
209 modesettingPtr ms = modesettingPTR(pScrn);
210 //ScreenPtr pScreen = pScrn->pScreen;
211 //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
212 //Bool fbAccessDisabled;
213 //CARD8 *fbstart;
214
215 if (width == pScrn->virtualX && height == pScrn->virtualY)
216 return TRUE;
217
218 ErrorF("RESIZING TO %dx%d\n", width, height);
219
220 pScrn->virtualX = width;
221 pScrn->virtualY = height;
222
223 /* HW dependent - FIXME */
224 pScrn->displayWidth = pScrn->virtualX;
225
226 drmModeRmFB(ms->fd, ms->fb_id);
227
228 /* now create new frontbuffer */
229 return CreateFrontBuffer(pScrn);
230 }
231
232 static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
233 crtc_resize
234 };
235
236 static Bool
237 PreInit(ScrnInfoPtr pScrn, int flags)
238 {
239 xf86CrtcConfigPtr xf86_config;
240 modesettingPtr ms;
241 rgb defaultWeight = { 0, 0, 0 };
242 EntityInfoPtr pEnt;
243 EntPtr msEnt = NULL;
244 char *BusID;
245 int max_width, max_height;
246
247 if (pScrn->numEntities != 1)
248 return FALSE;
249
250 pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
251
252 if (flags & PROBE_DETECT) {
253 ProbeDDC(pScrn, pEnt->index);
254 return TRUE;
255 }
256
257 /* Allocate driverPrivate */
258 if (!GetRec(pScrn))
259 return FALSE;
260
261 ms = modesettingPTR(pScrn);
262 ms->SaveGeneration = -1;
263 ms->pEnt = pEnt;
264
265 pScrn->displayWidth = 640; /* default it */
266
267 if (ms->pEnt->location.type != BUS_PCI)
268 return FALSE;
269
270 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
271
272 /* Allocate an entity private if necessary */
273 if (xf86IsEntityShared(pScrn->entityList[0])) {
274 FatalError("Entity");
275 #if 0
276 msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
277 modesettingEntityIndex)->ptr;
278 ms->entityPrivate = msEnt;
279 #else
280 (void)msEnt;
281 #endif
282 } else
283 ms->entityPrivate = NULL;
284
285 if (xf86RegisterResources(ms->pEnt->index, NULL, ResNone)) {
286 return FALSE;
287 }
288
289 if (xf86IsEntityShared(pScrn->entityList[0])) {
290 if (xf86IsPrimInitDone(pScrn->entityList[0])) {
291 /* do something */
292 } else {
293 xf86SetPrimInitDone(pScrn->entityList[0]);
294 }
295 }
296
297 BusID = xalloc(64);
298 sprintf(BusID, "PCI:%d:%d:%d",
299 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
300 ms->PciInfo->dev, ms->PciInfo->func
301 );
302
303 ms->api = drm_api_create();
304 ms->fd = drmOpen(NULL, BusID);
305
306 if (ms->fd < 0)
307 return FALSE;
308
309 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
310 pScrn->monitor = pScrn->confScreen->monitor;
311 pScrn->progClock = TRUE;
312 pScrn->rgbBits = 8;
313
314 if (!xf86SetDepthBpp
315 (pScrn, 0, 0, 0,
316 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
317 return FALSE;
318
319 switch (pScrn->depth) {
320 case 15:
321 case 16:
322 case 24:
323 break;
324 default:
325 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
326 "Given depth (%d) is not supported by the driver\n",
327 pScrn->depth);
328 return FALSE;
329 }
330 xf86PrintDepthBpp(pScrn);
331
332 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
333 return FALSE;
334 if (!xf86SetDefaultVisual(pScrn, -1))
335 return FALSE;
336
337 /* Process the options */
338 xf86CollectOptions(pScrn, NULL);
339 if (!(ms->Options = xalloc(sizeof(Options))))
340 return FALSE;
341 memcpy(ms->Options, Options, sizeof(Options));
342 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
343
344 /* Allocate an xf86CrtcConfig */
345 xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
346 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
347
348 max_width = 8192;
349 max_height = 8192;
350 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
351
352 if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
353 ms->SWCursor = TRUE;
354 }
355
356 SaveHWState(pScrn);
357
358 crtc_init(pScrn);
359 output_init(pScrn);
360
361 if (!xf86InitialConfiguration(pScrn, TRUE)) {
362 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
363 RestoreHWState(pScrn);
364 return FALSE;
365 }
366
367 RestoreHWState(pScrn);
368
369 /*
370 * If the driver can do gamma correction, it should call xf86SetGamma() here.
371 */
372 {
373 Gamma zeros = { 0.0, 0.0, 0.0 };
374
375 if (!xf86SetGamma(pScrn, zeros)) {
376 return FALSE;
377 }
378 }
379
380 if (pScrn->modes == NULL) {
381 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
382 return FALSE;
383 }
384
385 pScrn->currentMode = pScrn->modes;
386
387 /* Set display resolution */
388 xf86SetDpi(pScrn, 0, 0);
389
390 /* Load the required sub modules */
391 if (!xf86LoadSubModule(pScrn, "fb")) {
392 return FALSE;
393 }
394
395 xf86LoaderReqSymLists(fbSymbols, NULL);
396
397 xf86LoadSubModule(pScrn, "exa");
398
399 #ifdef DRI2
400 xf86LoadSubModule(pScrn, "dri2");
401 #endif
402
403 return TRUE;
404 }
405
406 static Bool
407 SaveHWState(ScrnInfoPtr pScrn)
408 {
409 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
410
411 return TRUE;
412 }
413
414 static Bool
415 RestoreHWState(ScrnInfoPtr pScrn)
416 {
417 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
418
419 return TRUE;
420 }
421
422 static Bool
423 CreateScreenResources(ScreenPtr pScreen)
424 {
425 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
426 modesettingPtr ms = modesettingPTR(pScrn);
427 PixmapPtr rootPixmap;
428 Bool ret;
429
430 ms->noEvict = TRUE;
431
432 pScreen->CreateScreenResources = ms->createScreenResources;
433 ret = pScreen->CreateScreenResources(pScreen);
434 pScreen->CreateScreenResources = CreateScreenResources;
435
436 rootPixmap = pScreen->GetScreenPixmap(pScreen);
437
438 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
439 FatalError("Couldn't adjust screen pixmap\n");
440
441 ms->noEvict = FALSE;
442
443 drmModeAddFB(ms->fd,
444 pScrn->virtualX,
445 pScrn->virtualY,
446 pScrn->depth,
447 pScrn->bitsPerPixel,
448 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
449 xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
450
451 AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
452
453 return ret;
454 }
455
456 static Bool
457 ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
458 {
459 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
460 modesettingPtr ms = modesettingPTR(pScrn);
461 VisualPtr visual;
462
463 /* deal with server regeneration */
464 if (ms->fd < 0) {
465 char *BusID;
466
467 BusID = xalloc(64);
468 sprintf(BusID, "PCI:%d:%d:%d",
469 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
470 ms->PciInfo->dev, ms->PciInfo->func
471 );
472
473 ms->fd = drmOpen(NULL, BusID);
474
475 if (ms->fd < 0)
476 return FALSE;
477 }
478
479 if (!ms->screen) {
480 ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
481
482 if (!ms->screen) {
483 FatalError("Could not init pipe_screen\n");
484 return FALSE;
485 }
486 }
487
488 pScrn->pScreen = pScreen;
489
490 /* HW dependent - FIXME */
491 pScrn->displayWidth = pScrn->virtualX;
492
493 miClearVisualTypes();
494
495 if (!miSetVisualTypes(pScrn->depth,
496 miGetDefaultVisualMask(pScrn->depth),
497 pScrn->rgbBits, pScrn->defaultVisual))
498 return FALSE;
499
500 if (!miSetPixmapDepths())
501 return FALSE;
502
503 pScrn->memPhysBase = 0;
504 pScrn->fbOffset = 0;
505
506 if (!fbScreenInit(pScreen, NULL,
507 pScrn->virtualX, pScrn->virtualY,
508 pScrn->xDpi, pScrn->yDpi,
509 pScrn->displayWidth, pScrn->bitsPerPixel))
510 return FALSE;
511
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;
523 }
524 }
525 }
526
527 fbPictureInit(pScreen, NULL, 0);
528
529 ms->createScreenResources = pScreen->CreateScreenResources;
530 pScreen->CreateScreenResources = CreateScreenResources;
531
532 xf86SetBlackWhitePixels(pScreen);
533
534 ms->exa = xorg_exa_init(pScrn);
535
536 miInitializeBackingStore(pScreen);
537 xf86SetBackingStore(pScreen);
538 xf86SetSilkenMouse(pScreen);
539 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
540
541 /* Need to extend HWcursor support to handle mask interleave */
542 if (!ms->SWCursor)
543 xf86_cursors_init(pScreen, 64, 64,
544 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
545 HARDWARE_CURSOR_ARGB);
546
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;
550
551 pScreen->SaveScreen = xf86SaveScreen;
552 ms->CloseScreen = pScreen->CloseScreen;
553 pScreen->CloseScreen = CloseScreen;
554
555 if (!xf86CrtcScreenInit(pScreen))
556 return FALSE;
557
558 if (!miCreateDefColormap(pScreen))
559 return FALSE;
560
561 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
562
563 if (serverGeneration == 1)
564 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
565
566 #if 1
567 #ifdef DRI2
568 driScreenInit(pScreen);
569 #endif
570 #endif
571
572 return EnterVT(scrnIndex, 1);
573 }
574
575 static void
576 AdjustFrame(int scrnIndex, int x, int y, int flags)
577 {
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;
582
583 if (crtc && crtc->enabled) {
584 crtc->funcs->mode_set(crtc, pScrn->currentMode, pScrn->currentMode, x,
585 y);
586 crtc->x = output->initial_x + x;
587 crtc->y = output->initial_y + y;
588 }
589 }
590
591 static void
592 FreeScreen(int scrnIndex, int flags)
593 {
594 FreeRec(xf86Screens[scrnIndex]);
595 }
596
597 /* HACK */
598 void
599 cursor_destroy(xf86CrtcPtr crtc);
600
601 static void
602 LeaveVT(int scrnIndex, int flags)
603 {
604 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
605 modesettingPtr ms = modesettingPTR(pScrn);
606 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
607 int o;
608
609 for (o = 0; o < config->num_crtc; o++) {
610 xf86CrtcPtr crtc = config->crtc[o];
611
612 cursor_destroy(crtc);
613
614 if (crtc->rotatedPixmap || crtc->rotatedData) {
615 crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
616 crtc->rotatedData);
617 crtc->rotatedPixmap = NULL;
618 crtc->rotatedData = NULL;
619 }
620 }
621
622 drmModeRmFB(ms->fd, ms->fb_id);
623
624 RestoreHWState(pScrn);
625
626 pScrn->vtSema = FALSE;
627 }
628
629 /*
630 * This gets called when gaining control of the VT, and from ScreenInit().
631 */
632 static Bool
633 EnterVT(int scrnIndex, int flags)
634 {
635 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
636 modesettingPtr ms = modesettingPTR(pScrn);
637
638 /*
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.
641 */
642 if (ms->SaveGeneration != serverGeneration) {
643 ms->SaveGeneration = serverGeneration;
644 SaveHWState(pScrn);
645 }
646
647 if (!flags) /* signals startup as we'll do this in CreateScreenResources */
648 CreateFrontBuffer(pScrn);
649
650 if (!xf86SetDesiredModes(pScrn))
651 return FALSE;
652
653 return TRUE;
654 }
655
656 static Bool
657 SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
658 {
659 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
660
661 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
662 }
663
664 static Bool
665 CloseScreen(int scrnIndex, ScreenPtr pScreen)
666 {
667 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
668 modesettingPtr ms = modesettingPTR(pScrn);
669
670 if (pScrn->vtSema) {
671 LeaveVT(scrnIndex, 0);
672 }
673 #ifdef DRI2
674 driCloseScreen(pScreen);
675 #endif
676
677 pScreen->CreateScreenResources = ms->createScreenResources;
678
679 if (ms->exa)
680 xorg_exa_close(pScrn);
681
682 ms->api->destroy(ms->api);
683 ms->api = NULL;
684 drmClose(ms->fd);
685 ms->fd = -1;
686
687 pScrn->vtSema = FALSE;
688 pScreen->CloseScreen = ms->CloseScreen;
689 return (*pScreen->CloseScreen) (scrnIndex, pScreen);
690 }
691
692 static ModeStatus
693 ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
694 {
695 return MODE_OK;
696 }
697
698 /* vim: set sw=4 ts=8 sts=4: */