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