add HW cursor support using drm-plane
[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);
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);
666         }
667
668         if (pOMAP->dri && pOMAP->pOMAPEXA) {
669                 pOMAP->dri = OMAPDRI2ScreenInit(pScreen);
670         } else {
671                 pOMAP->dri = FALSE;
672         }
673 }
674
675 /**
676  * The driver's ScreenInit() function.  Fill in pScreen, map the frame buffer,
677  * save state, initialize the mode, etc.
678  */
679 static Bool
680 OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
681 {
682         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
683         OMAPPtr pOMAP = OMAPPTR(pScrn);
684         VisualPtr visual;
685         xf86CrtcConfigPtr xf86_config;
686         int i;
687
688         TRACE_ENTER();
689
690         /* Allocate and map memory areas we need */
691         if (!OMAPMapMem(pScrn))
692                 return FALSE;
693
694         xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
695
696         /* need to point to new screen on server regeneration */
697         for (i = 0; i < xf86_config->num_crtc; i++)
698                 xf86_config->crtc[i]->scrn = pScrn;
699         for (i = 0; i < xf86_config->num_output; i++)
700                 xf86_config->output[i]->scrn = pScrn;
701
702         /*
703          * The next step is to setup the screen's visuals, and initialize the
704          * framebuffer code.  In cases where the framebuffer's default
705          * choices for things like visual layouts and bits per RGB are OK,
706          * this may be as simple as calling the framebuffer's ScreenInit()
707          * function.  If not, the visuals will need to be setup before calling
708          * a fb ScreenInit() function and fixed up after.
709          *
710          * For most PC hardware at depths >= 8, the defaults that fb uses
711          * are not appropriate.  In this driver, we fixup the visuals after.
712          */
713
714         /*
715          * Reset the visual list.
716          */
717
718         miClearVisualTypes();
719         if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
720                         pScrn->rgbBits, pScrn->defaultVisual)) {
721                 ERROR_MSG("Cannot initialize the visual type for %d bits per pixel!",
722                                 pScrn->bitsPerPixel);
723                 goto fail;
724         }
725
726         if (!miSetPixmapDepths()) {
727                 ERROR_MSG("Cannot initialize the pixmap depth!");
728                 goto fail;
729         }
730
731         /* Initialize some generic 2D drawing functions: */
732         if (!fbScreenInit(pScreen, omap_bo_map(pOMAP->scanout),
733                         pScrn->virtualX, pScrn->virtualY,
734                         pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
735                         pScrn->bitsPerPixel)) {
736                 ERROR_MSG("fbScreenInit() failed!");
737                 goto fail;
738         }
739
740         /* Fixup RGB ordering: */
741         visual = pScreen->visuals + pScreen->numVisuals;
742         while (--visual >= pScreen->visuals) {
743                 if ((visual->class | DynamicClass) == DirectColor) {
744                         visual->offsetRed = pScrn->offset.red;
745                         visual->offsetGreen = pScrn->offset.green;
746                         visual->offsetBlue = pScrn->offset.blue;
747                         visual->redMask = pScrn->mask.red;
748                         visual->greenMask = pScrn->mask.green;
749                         visual->blueMask = pScrn->mask.blue;
750                 }
751         }
752
753         /* Continue initializing the generic 2D drawing functions after fixing the
754          * RGB ordering:
755          */
756         if (!fbPictureInit(pScreen, NULL, 0)) {
757                 ERROR_MSG("fbPictureInit() failed!");
758                 goto fail;
759         }
760
761         /* Set the initial black & white colormap indices: */
762         xf86SetBlackWhitePixels(pScreen);
763
764         /* Initialize external sub-modules for EXA now, this has to be before
765          * miDCInitialize() otherwise stacking order for wrapped ScreenPtr fxns
766          * ends up in the wrong order.
767          */
768         OMAPAccelInit(pScreen);
769
770         /* Initialize backing store: */
771         miInitializeBackingStore(pScreen);
772         xf86SetBackingStore(pScreen);
773
774         /* Cause the cursor position to be updated by the mouse signal handler: */
775         xf86SetSilkenMouse(pScreen);
776
777         /* Initialize the cursor: */
778         miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
779
780         if (pOMAP->HWCursor) {
781                 if (!drmmode_cursor_init(pScreen)) {
782                         ERROR_MSG("Hardware cursor initialization failed");
783                         pOMAP->HWCursor = FALSE;
784                 }
785         }
786
787         /* XXX -- Is this the right place for this?  The Intel i830 driver says:
788          * "Must force it before EnterVT, so we are in control of VT..."
789          */
790         pScrn->vtSema = TRUE;
791
792         /* Take over the virtual terminal from the console, set the desired mode,
793          * etc.:
794          */
795         OMAPEnterVT(scrnIndex, 0);
796
797         /* Set the desired mode(s): */
798         if (!xf86SetDesiredModes(pScrn)) {
799                 ERROR_MSG("xf86SetDesiredModes() failed!");
800                 goto fail;
801         }
802
803         /* Do some XRandR initialization: */
804         if (!xf86CrtcScreenInit(pScreen)) {
805                 ERROR_MSG("xf86CrtcScreenInit() failed!");
806                 goto fail;
807         }
808
809         if (!miCreateDefColormap(pScreen)) {
810                 ERROR_MSG("Cannot create colormap!");
811                 goto fail;
812         }
813
814         if (!xf86HandleColormaps(pScreen, 256, 8, OMAPLoadPalette, NULL,
815                         CMAP_PALETTED_TRUECOLOR)) {
816                 ERROR_MSG("xf86HandleColormaps() failed!");
817                 goto fail;
818         }
819
820         /* Setup power management: */
821         xf86DPMSInit(pScreen, xf86DPMSSet, 0);
822
823         pScreen->SaveScreen = xf86SaveScreen;
824
825         /* Wrap some screen functions: */
826         wrap(pOMAP, pScreen, CloseScreen, OMAPCloseScreen);
827         wrap(pOMAP, pScreen, CreateScreenResources, OMAPCreateScreenResources);
828         wrap(pOMAP, pScreen, BlockHandler, OMAPBlockHandler);
829
830         drmmode_screen_init(pScrn);
831
832         TRACE_EXIT();
833         return TRUE;
834
835 fail:
836         TRACE_EXIT();
837         return FALSE;
838 }
839
840
841 static void
842 OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
843                 LOCO * colors, VisualPtr pVisual)
844 {
845         TRACE_ENTER();
846         TRACE_EXIT();
847 }
848
849
850 /**
851  * The driver's CloseScreen() function.  This is called at the end of each
852  * server generation.  Restore state, unmap the frame buffer (and any other
853  * mapped memory regions), and free per-Screen data structures (except those
854  * held by pScrn).
855  */
856 static Bool
857 OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen)
858 {
859         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
860         OMAPPtr pOMAP = OMAPPTR(pScrn);
861
862         TRACE_ENTER();
863
864         drmmode_screen_fini(pScrn);
865
866         if (pScrn->vtSema == TRUE) {
867                 OMAPLeaveVT(scrnIndex, 0);
868         }
869
870         if (pOMAP->pOMAPEXA) {
871                 if (pOMAP->pOMAPEXA->CloseScreen) {
872                         pOMAP->pOMAPEXA->CloseScreen(scrnIndex, pScreen);
873                 }
874         }
875
876         if (pOMAP->dri) {
877                 OMAPDRI2CloseScreen(pScreen);
878         }
879
880         OMAPUnmapMem(pScrn);
881
882         pScrn->vtSema = FALSE;
883
884         unwrap(pOMAP, pScreen, CloseScreen);
885         unwrap(pOMAP, pScreen, BlockHandler);
886         unwrap(pOMAP, pScreen, CreateScreenResources);
887
888         TRACE_EXIT();
889
890         return (*pScreen->CloseScreen)(scrnIndex, pScreen);
891 }
892
893
894
895 /**
896  * Adjust the screen pixmap for the current location of the front buffer.
897  * This is done at EnterVT when buffers are bound as long as the resources
898  * have already been created, but the first EnterVT happens before
899  * CreateScreenResources.
900  */
901 static Bool
902 OMAPCreateScreenResources(ScreenPtr pScreen)
903 {
904         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
905         OMAPPtr pOMAP = OMAPPTR(pScrn);
906
907         swap(pOMAP, pScreen, CreateScreenResources);
908         if (!(*pScreen->CreateScreenResources) (pScreen))
909                 return FALSE;
910         swap(pOMAP, pScreen, CreateScreenResources);
911
912         return TRUE;
913 }
914
915
916 static void
917 OMAPBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
918 {
919         ScreenPtr pScreen = screenInfo.screens[i];
920         ScrnInfoPtr pScrn = xf86Screens[i];
921         OMAPPtr pOMAP = OMAPPTR(pScrn);
922
923         swap(pOMAP, pScreen, BlockHandler);
924         (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
925         swap(pOMAP, pScreen, BlockHandler);
926
927         /* TODO OMAPVideoBlockHandler(), etc.. */
928 }
929
930
931
932 /**
933  * The driver's SwitchMode() function.  Initialize the new mode for the
934  * Screen.
935  */
936 static Bool
937 OMAPSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
938 {
939         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
940         return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
941 }
942
943
944
945 /**
946  * The driver's AdjustFrame() function.  For cases where the frame buffer is
947  * larger than the monitor resolution, this function can pan around the frame
948  * buffer within the "viewport" of the monitor.
949  */
950 static void
951 OMAPAdjustFrame(int scrnIndex, int x, int y, int flags)
952 {
953         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
954         drmmode_adjust_frame(pScrn, x, y, flags);
955 }
956
957
958
959 /**
960  * The driver's EnterVT() function.  This is called at server startup time, and
961  * when the X server takes over the virtual terminal from the console.  As
962  * such, it may need to save the current (i.e. console) HW state, and set the
963  * HW state as needed by the X server.
964  */
965 static Bool
966 OMAPEnterVT(int scrnIndex, int flags)
967 {
968         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
969         OMAPPtr pOMAP = OMAPPTR(pScrn);
970         int ret;
971
972         TRACE_ENTER();
973
974         ret = drmSetMaster(pOMAP->drmFD);
975         if (ret) {
976                 ERROR_MSG("Cannot get DRM master: %s\n", strerror(ret));
977         }
978
979         if (!xf86SetDesiredModes(pScrn)) {
980                 ERROR_MSG("xf86SetDesiredModes() failed!");
981                 return FALSE;
982         }
983
984         TRACE_EXIT();
985         return TRUE;
986 }
987
988
989
990 /**
991  * The driver's LeaveVT() function.  This is called when the X server
992  * temporarily gives up the virtual terminal to the console.  As such, it may
993  * need to restore the console's HW state.
994  */
995 static void
996 OMAPLeaveVT(int scrnIndex, int flags)
997 {
998         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
999         OMAPPtr pOMAP = OMAPPTR(pScrn);
1000         int ret;
1001
1002         TRACE_ENTER();
1003
1004         ret = drmDropMaster(pOMAP->drmFD);
1005         if (ret) {
1006                 WARNING_MSG("drmDropMaster failed: %s\n", strerror(errno));
1007         }
1008
1009         TRACE_EXIT();
1010 }
1011
1012
1013
1014 /**
1015  * The driver's FreeScreen() function.  This is called at the server's end of
1016  * life.  This should free any driver-allocated data that was allocated
1017  * up-to-and-including an unsuccessful ScreenInit() call.
1018  */
1019 static void
1020 OMAPFreeScreen(int scrnIndex, int flags)
1021 {
1022         ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1023         OMAPPtr pOMAP = OMAPPTR(pScrn);
1024
1025         TRACE_ENTER();
1026
1027         if (!pOMAP) {
1028                 /* This can happen if a Screen is deleted after Probe(): */
1029                 return;
1030         }
1031
1032         if (pOMAP->pOMAPEXA) {
1033                 if (pOMAP->pOMAPEXA->FreeScreen) {
1034                         pOMAP->pOMAPEXA->FreeScreen(scrnIndex, flags);
1035                 }
1036                 free(pOMAP->pOMAPEXA);
1037         }
1038
1039         omap_device_del(pOMAP->dev);
1040
1041         OMAPCloseDRMMaster(pScrn);
1042
1043         OMAPFreeRec(pScrn);
1044
1045         TRACE_EXIT();
1046 }
1047