initial commit
[ubuntu-omap:rsalvetis-xf86-video-omap.git] / src / omap_driver.c
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4  * Copyright © 2011 Texas Instruments, Inc
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Authors:
26  *    Ian Elliott <ianelliottus@yahoo.com>
27  *    Rob Clark <rob@ti.com>
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "omap_driver.h"
35
36
37 Bool omapDebug = 0;
38
39 /*
40  * Forward declarations:
41  */
42 static const OptionInfoRec *OMAPAvailableOptions(int chipid, int busid);
43 static void OMAPIdentify(int flags);
44 static Bool OMAPProbe(DriverPtr drv, int flags);
45 static Bool OMAPPreInit(ScrnInfoPtr pScrn, int flags);
46 static Bool OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
47                 char **argv);
48 static void OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
49                 LOCO * colors, VisualPtr pVisual);
50 static Bool OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen);
51 static Bool OMAPCreateScreenResources(ScreenPtr pScreen);
52 static void OMAPBlockHandler(int i, pointer blockData, pointer pTimeout,
53                 pointer pReadmask);
54 static Bool OMAPSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
55 static void OMAPAdjustFrame(int scrnIndex, int x, int y, int flags);
56 static Bool OMAPEnterVT(int scrnIndex, int flags);
57 static void OMAPLeaveVT(int scrnIndex, int flags);
58 static void OMAPFreeScreen(int scrnIndex, int flags);
59
60
61
62 /**
63  * A structure used by the XFree86 code when loading this driver, so that it
64  * can access the Probe() function, and other functions/info that it uses
65  * before it calls the Probe() function.  The name of this structure must be
66  * the all-upper-case version of the driver name.
67  */
68 _X_EXPORT DriverRec OMAP = {
69                 OMAP_VERSION,
70                 (char *)OMAP_DRIVER_NAME,
71                 OMAPIdentify,
72                 OMAPProbe,
73                 OMAPAvailableOptions,
74                 NULL,
75                 0,
76                 NULL,
77 #ifdef XSERVER_LIBPCIACCESS
78                 NULL,
79                 NULL
80 #endif
81 };
82
83 /** Supported "chipsets." */
84 static SymTabRec OMAPChipsets[] = {
85                 /* OMAP2 and earlier not supported */
86                 { 0x3430, "OMAP3430 with PowerVR SGX530" },
87                 { 0x3630, "OMAP3630 with PowerVR SGX530" },
88                 { 0x4430, "OMAP4430 with PowerVR SGX540" },
89                 { 0x4460, "OMAP4460 with PowerVR SGX540" },
90                 /*    { 4470, "OMAP4470 with <redacted> ;-)" }, */
91                 {-1, NULL }
92 };
93
94 /** Supported options, as enum values. */
95 typedef enum {
96         OPTION_DEBUG,
97         OPTION_NO_ACCEL,
98         /* TODO: probably need to add an option to let user specify bus-id */
99 } OMAPOpts;
100
101 /** Supported options. */
102 static const OptionInfoRec OMAPOptions[] = {
103         { OPTION_DEBUG,         "Debug",        OPTV_BOOLEAN,   {0},    FALSE },
104         { OPTION_NO_ACCEL,      "NoAccel",      OPTV_BOOLEAN,   {0},    FALSE },
105         { -1,                           NULL,           OPTV_NONE,              {0},    FALSE }
106 };
107
108 /**
109  * Helper function for opening a connection to the DRM.
110  */
111
112 static int
113 OMAPOpenDRM(int n)
114 {
115         char bus_id[32];
116         snprintf(bus_id, sizeof(bus_id), "platform:omapdrm:%02d", n);
117         return drmOpen("omapdrm", bus_id);
118 }
119
120 static Bool
121 OMAPOpenDRMMaster(ScrnInfoPtr pScrn, int n)
122 {
123         OMAPPtr pOMAP = OMAPPTR(pScrn);
124         drmSetVersion sv;
125         int err;
126
127         pOMAP->drmFD = OMAPOpenDRM(n);
128         if (pOMAP->drmFD == -1) {
129                 ERROR_MSG("Cannot open a connection with the DRM.");
130                 return FALSE;
131         }
132
133         /* Check that what we opened was a master or a master-capable FD,
134          * by setting the version of the interface we'll use to talk to it.
135          * (see DRIOpenDRMMaster() in DRI1)
136          */
137         sv.drm_di_major = 1;
138         sv.drm_di_minor = 1;
139         sv.drm_dd_major = -1;
140         sv.drm_dd_minor = -1;
141         err = drmSetInterfaceVersion(pOMAP->drmFD, &sv);
142         if (err != 0) {
143                 ERROR_MSG("Cannot set the DRM interface version.");
144                 drmClose(pOMAP->drmFD);
145                 pOMAP->drmFD = -1;
146                 return FALSE;
147         }
148
149         return TRUE;
150 }
151
152
153
154 /**
155  * Helper function for closing a connection to the DRM.
156  */
157 static void
158 OMAPCloseDRMMaster(ScrnInfoPtr pScrn)
159 {
160         OMAPPtr pOMAP = OMAPPTR(pScrn);
161
162         if (pOMAP && (pOMAP->drmFD > 0)) {
163                 drmClose(pOMAP->drmFD);
164                 pOMAP->drmFD = -1;
165         }
166 }
167
168
169
170 /**
171  * Helper function for calculating the stride of pixmaps.
172  * TODO get stride requirements from kernel driver, or from EXA module,
173  * rather than hard-coding..
174  */
175 #define STRIDE_BOUNDARY 32
176 unsigned int
177 OMAPCalculateStride(unsigned int width, unsigned int bitsPerPixel)
178 {
179         unsigned int alignedWidth;
180
181         alignedWidth = (width + (STRIDE_BOUNDARY - 1)) & ~(STRIDE_BOUNDARY - 1);
182         return ((alignedWidth * bitsPerPixel) + 7) / 8;
183 }
184
185
186 static Bool
187 OMAPMapMem(ScrnInfoPtr pScrn)
188 {
189         OMAPPtr pOMAP = OMAPPTR(pScrn);
190         int pitch;
191
192         pitch = OMAPCalculateStride(pScrn->virtualX, pScrn->bitsPerPixel);
193
194         DEBUG_MSG("allocating new scanout buffer: %dx%d (%d)",
195                         pScrn->virtualX, pScrn->virtualY, pitch);
196
197         pOMAP->scanout = omap_bo_new(pOMAP->dev, pScrn->virtualY * pitch,
198                         OMAP_BO_SCANOUT | OMAP_BO_WC);
199         if (!pOMAP->scanout) {
200                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
201                            "Error allocating scanout buffer\n");
202                 return FALSE;
203         }
204
205         pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
206
207         return TRUE;
208 }
209
210
211 static Bool
212 OMAPUnmapMem(ScrnInfoPtr pScrn)
213 {
214         OMAPPtr pOMAP = OMAPPTR(pScrn);
215         drmmode_remove_fb(pScrn);
216         omap_bo_del(pOMAP->scanout);
217         pOMAP->scanout = NULL;
218         return TRUE;
219 }
220
221
222
223 /** Let the XFree86 code know the Setup() function. */
224 static MODULESETUPPROTO(OMAPSetup);
225
226 /** Provide basic version information to the XFree86 code. */
227 static XF86ModuleVersionInfo OMAPVersRec =
228 {
229                 OMAP_DRIVER_NAME,
230                 MODULEVENDORSTRING,
231                 MODINFOSTRING1,
232                 MODINFOSTRING2,
233                 XORG_VERSION_CURRENT,
234                 OMAP_MAJOR_VERSION, OMAP_MINOR_VERSION, OMAP_PATCHLEVEL,
235                 ABI_CLASS_VIDEODRV,
236                 ABI_VIDEODRV_VERSION,
237                 MOD_CLASS_VIDEODRV,
238                 {0, 0, 0, 0}
239 };
240
241 /** Let the XFree86 code know about the VersRec and Setup() function. */
242 _X_EXPORT XF86ModuleData omapModuleData = { &OMAPVersRec, OMAPSetup, NULL };
243
244
245 /**
246  * The first function that the XFree86 code calls, after loading this module.
247  */
248 static pointer
249 OMAPSetup(pointer module, pointer opts, int *errmaj, int *errmin)
250 {
251         static Bool setupDone = FALSE;
252
253         /* This module should be loaded only once, but check to be sure: */
254         if (!setupDone) {
255                 setupDone = TRUE;
256                 xf86AddDriver(&OMAP, module, 0);
257
258                 /* The return value must be non-NULL on success even though there is no
259                  * TearDownProc.
260                  */
261                 return (pointer) 1;
262         } else {
263                 if (errmaj)
264                         *errmaj = LDR_ONCEONLY;
265                 return NULL;
266         }
267 }
268
269
270 /**
271  * Allocate the driver's Screen-specific, "private" data structure and hook it
272  * into the ScrnInfoRec's driverPrivate field.
273  */
274 static Bool
275 OMAPGetRec(ScrnInfoPtr pScrn)
276 {
277         if (pScrn->driverPrivate != NULL)
278                 return TRUE;
279
280         pScrn->driverPrivate = calloc(1, sizeof(OMAPRec));
281         if (pScrn->driverPrivate == NULL)
282                 return FALSE;
283
284         return TRUE;
285 }
286
287
288 /**
289  * Free the driver's Screen-specific, "private" data structure and NULL-out the
290  * ScrnInfoRec's driverPrivate field.
291  */
292 static void
293 OMAPFreeRec(ScrnInfoPtr pScrn)
294 {
295         if (pScrn->driverPrivate == NULL)
296                 return;
297         free(pScrn->driverPrivate);
298         pScrn->driverPrivate = NULL;
299 }
300
301
302 /**
303  * The mandatory AvailableOptions() function.  It returns the available driver
304  * options to the "-configure" option, so that an xorg.conf file can be built
305  * and the user can see which options are available for them to use.
306  */
307 static const OptionInfoRec *
308 OMAPAvailableOptions(int chipid, int busid)
309 {
310         return OMAPOptions;
311 }
312
313
314
315 /**
316  * The mandatory Identify() function.  It is run before Probe(), and prints out
317  * an identifying message, which includes the chipset(s) the driver supports.
318  */
319 static void
320 OMAPIdentify(int flags)
321 {
322         xf86PrintChipsets(OMAP_NAME, "Driver for TI OMAP", OMAPChipsets);
323 }
324
325
326
327 /**
328  * The driver's Probe() function.  This function finds all instances of the
329  * TI OMAP hardware that the driver supports (from within the "xorg.conf"
330  * device sections), and for instances not already claimed by another driver,
331  * claim the instances, and allocate a ScrnInfoRec.  Only minimal hardware
332  * probing is allowed here.
333  */
334 static Bool
335 OMAPProbe(DriverPtr drv, int flags)
336 {
337         int i;
338         ScrnInfoPtr pScrn;
339         GDevPtr *devSections;
340         int numDevSections;
341         Bool foundScreen = FALSE;
342
343         if (flags & PROBE_DETECT) {
344                 EARLY_ERROR_MSG("The %s driver does not support the \"-configure\" or "
345                                 "\"-probe\" command line arguments.", OMAP_NAME);
346                 return FALSE;
347         }
348
349         /* Get the "xorg.conf" file device sections that match this driver, and
350          * return (error out) if there are none:
351          */
352         numDevSections = xf86MatchDevice(OMAP_DRIVER_NAME, &devSections);
353         if (numDevSections <= 0) {
354                 EARLY_ERROR_MSG("Did not find any matching device section in "
355                                 "configuration file");
356                 return FALSE;
357         }
358
359         for (i = 0; i < numDevSections; i++) {
360                 int fd = OMAPOpenDRM(i);
361                 if (fd != -1) {
362                         int entity = xf86ClaimNoSlot(drv, 0, devSections[i], TRUE);
363
364                         pScrn = xf86AllocateScreen(drv, 0);
365                         if (!pScrn) {
366                                 EARLY_ERROR_MSG("Cannot allocate a ScrnInfoPtr");
367                                 return FALSE;
368                         }
369                         xf86AddEntityToScreen(pScrn, entity);
370
371                         foundScreen = TRUE;
372
373                         pScrn->driverVersion = OMAP_VERSION;
374                         pScrn->driverName    = (char *)OMAP_DRIVER_NAME;
375                         pScrn->name          = (char *)OMAP_NAME;
376                         pScrn->Probe         = OMAPProbe;
377                         pScrn->PreInit       = OMAPPreInit;
378                         pScrn->ScreenInit    = OMAPScreenInit;
379                         pScrn->SwitchMode    = OMAPSwitchMode;
380                         pScrn->AdjustFrame   = OMAPAdjustFrame;
381                         pScrn->EnterVT       = OMAPEnterVT;
382                         pScrn->LeaveVT       = OMAPLeaveVT;
383                         pScrn->FreeScreen    = OMAPFreeScreen;
384
385                         /* would be nice to be able to keep the connection open.. but
386                          * currently we don't allocate the private until PreInit
387                          */
388                         drmClose(fd);
389                 }
390         }
391         free(devSections);
392         return foundScreen;
393 }
394
395
396
397 /**
398  * The driver's PreInit() function.  Additional hardware probing is allowed
399  * now, including display configuration.
400  */
401 static Bool
402 OMAPPreInit(ScrnInfoPtr pScrn, int flags)
403 {
404         OMAPPtr pOMAP;
405         int default_depth, fbbpp;
406         rgb defaultWeight = { 0, 0, 0 };
407         rgb defaultMask = { 0, 0, 0 };
408         Gamma defaultGamma = { 0.0, 0.0, 0.0 };
409         uint64_t value;
410         int i;
411
412         TRACE_ENTER();
413
414         if (flags & PROBE_DETECT) {
415                 ERROR_MSG("The %s driver does not support the \"-configure\" or "
416                                 "\"-probe\" command line arguments.", OMAP_NAME);
417                 return FALSE;
418         }
419
420         /* Check the number of entities, and fail if it isn't one. */
421         if (pScrn->numEntities != 1) {
422                 ERROR_MSG("Driver expected 1 entity, but found %d for screen %d",
423                                 pScrn->numEntities, pScrn->scrnIndex);
424                 return FALSE;
425         }
426
427         /* Allocate the driver's Screen-specific, "private" data structure: */
428         OMAPGetRec(pScrn);
429         pOMAP = OMAPPTR(pScrn);
430
431         pOMAP->pEntityInfo = xf86GetEntityInfo(pScrn->entityList[0]);
432
433         pScrn->monitor = pScrn->confScreen->monitor;
434
435         /* Get the current depth, and set it for XFree86: */
436         default_depth = 24;  /* TODO: get from kernel */
437         fbbpp = 32;  /* TODO: get from kernel */
438
439         if (!xf86SetDepthBpp(pScrn, default_depth, 0, fbbpp, Support32bppFb)) {
440                 /* The above function prints an error message. */
441                 goto fail;
442         }
443         xf86PrintDepthBpp(pScrn);
444
445         /* Set the color weight: */
446         if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) {
447                 /* The above function prints an error message. */
448                 goto fail;
449         }
450
451         /* Set the gamma: */
452         if (!xf86SetGamma(pScrn, defaultGamma)) {
453                 /* The above function prints an error message. */
454                 goto fail;
455         }
456
457         /* Visual init: */
458         if (!xf86SetDefaultVisual(pScrn, -1)) {
459                 /* The above function prints an error message. */
460                 goto fail;
461         }
462
463         /* We don't support 8-bit depths: */
464         if (pScrn->depth < 16) {
465                 ERROR_MSG("The requested default visual (%s) has an unsupported "
466                                 "depth (%d).",
467                                 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
468                 goto fail;
469         }
470
471         /* Using a programmable clock: */
472         pScrn->progClock = TRUE;
473
474         /* Open a connection to the DRM, so we can communicate with the KMS code: */
475         if (!OMAPOpenDRMMaster(pScrn, 0)) {
476                 goto fail;
477         }
478         DEBUG_MSG("Became DRM master.");
479
480         /* create DRM device instance: */
481         pOMAP->dev = omap_device_new(pOMAP->drmFD);
482
483         /* query chip-id: */
484         if (omap_get_param(pOMAP->dev, OMAP_PARAM_CHIPSET_ID, &value)) {
485                 ERROR_MSG("Could not read chipset");
486                 goto fail;
487         }
488         pOMAP->chipset = value;
489
490         /* find matching chipset name: */
491         for (i = 0; OMAPChipsets[i].name; i++) {
492                 if (OMAPChipsets[i].token == pOMAP->chipset) {
493                         pScrn->chipset = (char *)OMAPChipsets[i].name;
494                         break;
495                 }
496         }
497
498         if (!pScrn->chipset) {
499                 ERROR_MSG("Unknown chipset: %s", pScrn->chipset);
500                 goto fail;
501         }
502
503         INFO_MSG("Found chipset: %s", pScrn->chipset);
504
505         /*
506          * Process the "xorg.conf" file options:
507          */
508         xf86CollectOptions(pScrn, NULL);
509         if (!(pOMAP->pOptionInfo = calloc(1, sizeof(OMAPOptions))))
510                 return FALSE;
511         memcpy(pOMAP->pOptionInfo, OMAPOptions, sizeof(OMAPOptions));
512         xf86ProcessOptions(pScrn->scrnIndex, pOMAP->pEntityInfo->device->options,
513                         pOMAP->pOptionInfo);
514
515         /* Determine if the user wants debug messages turned on: */
516         omapDebug = xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_DEBUG, FALSE);
517
518         /* Determine if the user wants to disable acceleration: */
519         pOMAP->NoAccel =
520                         xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_NO_ACCEL, FALSE);
521
522         /*
523          * Select the video modes:
524          */
525         INFO_MSG("Setting the video modes ...");
526
527         /* Don't call drmCheckModesettingSupported() as its written only for
528          * PCI devices.
529          */
530
531         /* Do initial KMS setup: */
532         if (!drmmode_pre_init(pScrn, pOMAP->drmFD, (pScrn->bitsPerPixel >> 3))) {
533                 ERROR_MSG("Cannot get KMS resources");
534         } else {
535                 INFO_MSG("Got KMS resources");
536         }
537
538         xf86RandR12PreInit(pScrn);
539
540         /* Let XFree86 calculate or get (from command line) the display DPI: */
541         xf86SetDpi(pScrn, 0, 0);
542
543         /* Ensure we have a supported depth: */
544         switch (pScrn->bitsPerPixel) {
545         case 16:
546         case 24:
547         case 32:
548                 break;
549         default:
550                 ERROR_MSG("The requested number of bits per pixel (%d) is unsupported.",
551                                 pScrn->bitsPerPixel);
552                 goto fail;
553         }
554
555
556         /* Load external sub-modules now: */
557
558         if (!(xf86LoadSubModule(pScrn, "dri2") &&
559                         xf86LoadSubModule(pScrn, "exa") &&
560                         xf86LoadSubModule(pScrn, "fb"))) {
561                 goto fail;
562         }
563
564         switch (pOMAP->chipset) {
565         case 0x3430:
566         case 0x3630:
567         case 0x4430:
568         case 0x4460:
569                 if (xf86LoadSubModule(pScrn, SUB_MODULE_PVR)) {
570                         INFO_MSG("Loaded the %s sub-module", SUB_MODULE_PVR);
571                 } else {
572                         INFO_MSG("Cannot load the %s sub-module", SUB_MODULE_PVR);
573                         /* note that this is not fatal.. since IMG/PVR EXA module
574                          * is closed source, it is only optional.
575                          */
576                         pOMAP->NoAccel = TRUE;  /* don't call InitPowerVREXA() */
577                 }
578                 break;
579                 /* case 0x4470: ..; break; */
580         default:
581                 ERROR_MSG("Unsupported chipset: %d", pOMAP->chipset);
582                 goto fail;
583         }
584
585         TRACE_EXIT();
586         return TRUE;
587
588 fail:
589         TRACE_EXIT();
590         OMAPFreeRec(pScrn);
591         return FALSE;
592 }
593
594
595
596 /**
597  * The driver's ScreenInit() function.  Fill in pScreen, map the frame buffer,
598  * save state, initialize the mode, etc.
599  */
600 static Bool
601 OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
602 {
603         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
604         OMAPPtr pOMAP = OMAPPTR(pScrn);
605         VisualPtr visual;
606         xf86CrtcConfigPtr xf86_config;
607         int i;
608
609         TRACE_ENTER();
610
611 #if 0
612         if (!pOMAP->NoAccel)
613                 OMAPDRI2Init(pScreen);
614 #endif
615
616         /* Allocate and map memory areas we need */
617         if (!OMAPMapMem(pScrn))
618                 return FALSE;
619
620         xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
621
622         /* need to point to new screen on server regeneration */
623         for (i = 0; i < xf86_config->num_crtc; i++)
624                 xf86_config->crtc[i]->scrn = pScrn;
625         for (i = 0; i < xf86_config->num_output; i++)
626                 xf86_config->output[i]->scrn = pScrn;
627
628         /*
629          * The next step is to setup the screen's visuals, and initialize the
630          * framebuffer code.  In cases where the framebuffer's default
631          * choices for things like visual layouts and bits per RGB are OK,
632          * this may be as simple as calling the framebuffer's ScreenInit()
633          * function.  If not, the visuals will need to be setup before calling
634          * a fb ScreenInit() function and fixed up after.
635          *
636          * For most PC hardware at depths >= 8, the defaults that fb uses
637          * are not appropriate.  In this driver, we fixup the visuals after.
638          */
639
640         /*
641          * Reset the visual list.
642          */
643
644         miClearVisualTypes();
645         if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
646                         pScrn->rgbBits, pScrn->defaultVisual)) {
647                 ERROR_MSG("Cannot initialize the visual type for %d bits per pixel!",
648                                 pScrn->bitsPerPixel);
649                 goto fail;
650         }
651
652         if (!miSetPixmapDepths()) {
653                 ERROR_MSG("Cannot initialize the pixmap depth!");
654                 goto fail;
655         }
656
657 #if 0
658         // FIXME -- WRITE THE DRM/KMS VERSION OF THIS CODE!!!
659         // In the mean time, use the following code:
660         pScrn->displayWidth =
661                         fbdevHWGetLineLength(pScrn) / (pScrn->bitsPerPixel / 8);
662
663         /* Calculate where the actual frame buffer starts: */
664         pOMAP->fbstart = pOMAP->fbmem + pOMAP->fboff;
665         INFO_MSG("pOMAP->fbstart=%p, pOMAP->fbmem=%p, pOMAP->fboff=0x%x",
666                         pOMAP->fbstart, pOMAP->fbmem, pOMAP->fboff);
667         INFO_MSG("pScrn->displayWidth=%d", pScrn->displayWidth);
668 #endif
669
670         /* Initialize some generic 2D drawing functions: */
671         if (!fbScreenInit(pScreen, omap_bo_map(pOMAP->scanout),
672                         pScrn->virtualX, pScrn->virtualY,
673                         pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
674                         pScrn->bitsPerPixel)) {
675                 ERROR_MSG("fbScreenInit() failed!");
676                 goto fail;
677         }
678
679         /* Fixup RGB ordering: */
680         visual = pScreen->visuals + pScreen->numVisuals;
681         while (--visual >= pScreen->visuals) {
682                 if ((visual->class | DynamicClass) == DirectColor) {
683                         visual->offsetRed = pScrn->offset.red;
684                         visual->offsetGreen = pScrn->offset.green;
685                         visual->offsetBlue = pScrn->offset.blue;
686                         visual->redMask = pScrn->mask.red;
687                         visual->greenMask = pScrn->mask.green;
688                         visual->blueMask = pScrn->mask.blue;
689                 }
690         }
691
692         /* Continue initializing the generic 2D drawing functions after fixing the
693          * RGB ordering:
694          */
695         if (!fbPictureInit(pScreen, NULL, 0)) {
696                 ERROR_MSG("fbPictureInit() failed!");
697                 goto fail;
698         }
699
700         /* Set the initial black & white colormap indices: */
701         xf86SetBlackWhitePixels(pScreen);
702
703         /* Initialize backing store: */
704         miInitializeBackingStore(pScreen);
705         xf86SetBackingStore(pScreen);
706
707         /* Initialize the cursor: */
708         miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
709
710         /* Cause the cursor position to be updated by the mouse signal handler: */
711         xf86SetSilkenMouse(pScreen);
712
713         /* XXX -- Is this the right place for this?  The Intel i830 driver says:
714          * "Must force it before EnterVT, so we are in control of VT..."
715          */
716         pScrn->vtSema = TRUE;
717
718         /* Take over the virtual terminal from the console, set the desired mode,
719          * etc.:
720          */
721         OMAPEnterVT(scrnIndex, 0);
722
723         /* Set the desired mode(s): */
724         if (!xf86SetDesiredModes(pScrn)) {
725                 ERROR_MSG("xf86SetDesiredModes() failed!");
726                 goto fail;
727         }
728
729         /* Do some XRandR initialization: */
730         if (!xf86CrtcScreenInit(pScreen)) {
731                 ERROR_MSG("xf86CrtcScreenInit() failed!");
732                 goto fail;
733         }
734
735         if (!miCreateDefColormap(pScreen)) {
736                 ERROR_MSG("Cannot create colormap!");
737                 goto fail;
738         }
739
740         if (!xf86HandleColormaps(pScreen, 256, 8, OMAPLoadPalette, NULL,
741                         CMAP_PALETTED_TRUECOLOR)) {
742                 ERROR_MSG("xf86HandleColormaps() failed!");
743                 goto fail;
744         }
745
746         /* Setup power management: */
747         xf86DPMSInit(pScreen, xf86DPMSSet, 0);
748
749         pScreen->SaveScreen = xf86SaveScreen;
750
751         /* Wrap some screen functions: */
752         wrap(pOMAP, pScreen, CloseScreen, OMAPCloseScreen);
753         wrap(pOMAP, pScreen, CreateScreenResources, OMAPCreateScreenResources);
754         wrap(pOMAP, pScreen, BlockHandler, OMAPBlockHandler);
755
756         /*
757          * Initialize external sub-modules for EXA now:
758          */
759
760         if (!pOMAP->NoAccel) {
761                 switch (pOMAP->chipset) {
762                 case 0x3430:
763                 case 0x3630:
764                 case 0x4430:
765                 case 0x4460:
766                         INFO_MSG("Initializing the \"%s\" sub-module ...", SUB_MODULE_PVR);
767                         pOMAP->pOMAPEXA = InitPowerVREXA(pScreen, pScrn);
768                         if (pOMAP->pOMAPEXA) {
769                                 INFO_MSG("Successfully initialized the \"%s\" sub-module",
770                                                 SUB_MODULE_PVR);
771                         } else {
772                                 INFO_MSG("Could not initialize the \"%s\" sub-module",
773                                                 SUB_MODULE_PVR);
774                                 pOMAP->NoAccel = TRUE;
775                         }
776                         break;
777                         /* case 4470: ..; break; */
778                 default:
779                         ERROR_MSG("Unsupported chipset: %d", pOMAP->chipset);
780                         pOMAP->NoAccel = TRUE;
781                         break;
782                 }
783         }
784
785         if (!pOMAP->pOMAPEXA) {
786                 pOMAP->pOMAPEXA = InitNullEXA(pScreen, pScrn);
787         }
788
789         drmmode_uevent_init(pScrn);
790
791         TRACE_EXIT();
792         return TRUE;
793
794 fail:
795         TRACE_EXIT();
796         return FALSE;
797 }
798
799
800 static void
801 OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
802                 LOCO * colors, VisualPtr pVisual)
803 {
804         TRACE_ENTER();
805         TRACE_EXIT();
806 }
807
808
809 /**
810  * The driver's CloseScreen() function.  This is called at the end of each
811  * server generation.  Restore state, unmap the frame buffer (and any other
812  * mapped memory regions), and free per-Screen data structures (except those
813  * held by pScrn).
814  */
815 static Bool
816 OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen)
817 {
818         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
819         OMAPPtr pOMAP = OMAPPTR(pScrn);
820
821         TRACE_ENTER();
822
823         drmmode_uevent_fini(pScrn);
824
825         if (pScrn->vtSema == TRUE) {
826                 OMAPLeaveVT(scrnIndex, 0);
827         }
828
829         if (pOMAP->pOMAPEXA) {
830                 if (pOMAP->pOMAPEXA->CloseScreen) {
831                         pOMAP->pOMAPEXA->CloseScreen(scrnIndex, pScreen);
832                 }
833         }
834
835         OMAPUnmapMem(pScrn);
836
837         pScrn->vtSema = FALSE;
838
839         unwrap(pOMAP, pScreen, CloseScreen);
840         unwrap(pOMAP, pScreen, BlockHandler);
841         unwrap(pOMAP, pScreen, CreateScreenResources);
842
843         TRACE_EXIT();
844
845         return (*pScreen->CloseScreen)(scrnIndex, pScreen);
846 }
847
848
849
850 /**
851  * Adjust the screen pixmap for the current location of the front buffer.
852  * This is done at EnterVT when buffers are bound as long as the resources
853  * have already been created, but the first EnterVT happens before
854  * CreateScreenResources.
855  */
856 static Bool
857 OMAPCreateScreenResources(ScreenPtr pScreen)
858 {
859         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
860         OMAPPtr pOMAP = OMAPPTR(pScrn);
861
862         swap(pOMAP, pScreen, CreateScreenResources);
863         if (!(*pScreen->CreateScreenResources) (pScreen))
864                 return FALSE;
865         swap(pOMAP, pScreen, CreateScreenResources);
866
867         return TRUE;
868 }
869
870
871 static void
872 OMAPBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
873 {
874         ScreenPtr pScreen = screenInfo.screens[i];
875         ScrnInfoPtr pScrn = xf86Screens[i];
876         OMAPPtr pOMAP = OMAPPTR(pScrn);
877
878         swap(pOMAP, pScreen, BlockHandler);
879         (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
880         swap(pOMAP, pScreen, BlockHandler);
881
882         /* TODO OMAPVideoBlockHandler(), etc.. */
883 }
884
885
886
887 /**
888  * The driver's SwitchMode() function.  Initialize the new mode for the
889  * Screen.
890  */
891 static Bool
892 OMAPSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
893 {
894         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
895         return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
896 }
897
898
899
900 /**
901  * The driver's AdjustFrame() function.  For cases where the frame buffer is
902  * larger than the monitor resolution, this function can pan around the frame
903  * buffer within the "viewport" of the monitor.
904  */
905 static void
906 OMAPAdjustFrame(int scrnIndex, int x, int y, int flags)
907 {
908         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
909         drmmode_adjust_frame(pScrn, x, y, flags);
910 }
911
912
913
914 /**
915  * The driver's EnterVT() function.  This is called at server startup time, and
916  * when the X server takes over the virtual terminal from the console.  As
917  * such, it may need to save the current (i.e. console) HW state, and set the
918  * HW state as needed by the X server.
919  */
920 static Bool
921 OMAPEnterVT(int scrnIndex, int flags)
922 {
923         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
924         OMAPPtr pOMAP = OMAPPTR(pScrn);
925         int ret;
926
927         TRACE_ENTER();
928
929         ret = drmSetMaster(pOMAP->drmFD);
930         if (ret) {
931                 ERROR_MSG("Cannot get DRM master: %s\n", strerror(ret));
932         }
933
934         if (!xf86SetDesiredModes(pScrn)) {
935                 ERROR_MSG("xf86SetDesiredModes() failed!");
936                 return FALSE;
937         }
938
939         TRACE_EXIT();
940         return TRUE;
941 }
942
943
944
945 /**
946  * The driver's LeaveVT() function.  This is called when the X server
947  * temporarily gives up the virtual terminal to the console.  As such, it may
948  * need to restore the console's HW state.
949  */
950 static void
951 OMAPLeaveVT(int scrnIndex, int flags)
952 {
953         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
954         OMAPPtr pOMAP = OMAPPTR(pScrn);
955         int ret;
956
957         TRACE_ENTER();
958
959         ret = drmDropMaster(pOMAP->drmFD);
960         if (ret) {
961                 WARNING_MSG("drmDropMaster failed: %s\n", strerror(errno));
962         }
963
964         TRACE_EXIT();
965 }
966
967
968
969 /**
970  * The driver's FreeScreen() function.  This is called at the server's end of
971  * life.  This should free any driver-allocated data that was allocated
972  * up-to-and-including an unsuccessful ScreenInit() call.
973  */
974 static void
975 OMAPFreeScreen(int scrnIndex, int flags)
976 {
977         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
978         OMAPPtr pOMAP = OMAPPTR(pScrn);
979
980         TRACE_ENTER();
981
982         if (!pOMAP) {
983                 /* This can happen if a Screen is deleted after Probe(): */
984                 return;
985         }
986
987         if (pOMAP->pOMAPEXA) {
988                 if (pOMAP->pOMAPEXA->FreeScreen) {
989                         pOMAP->pOMAPEXA->FreeScreen(scrnIndex, flags);
990                 }
991                 free(pOMAP->pOMAPEXA);
992         }
993
994         omap_device_del(pOMAP->dev);
995
996         OMAPCloseDRMMaster(pScrn);
997
998         OMAPFreeRec(pScrn);
999
1000         TRACE_EXIT();
1001 }
1002