2 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
3 * Michel Dänzer, <michel@tungstengraphics.com>
5 /**************************************************************************
7 xserver-xorg-video-emulfb
9 Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
10 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
12 Contact: SooChan Lim <sc1.lim@samsung.com>
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
40 /* all driver need this */
42 #include "xf86_OSproc.h"
45 #include "mipointer.h"
48 #include "colormapst.h"
56 #include "fbdev_video.h"
57 #include "fbdev_crtcconfig.h"
58 #include "fbdev_dpms.h"
59 #include "fbdev_event_trace.h"
62 #include <sys/ioctl.h>
70 static const OptionInfoRec * FBDevAvailableOptions(int chipid, int busid);
71 static void FBDevIdentify(int flags);
72 static Bool FBDevProbe(DriverPtr drv, int flags);
73 static Bool FBDevPreInit(ScrnInfoPtr pScrn, int flags);
74 static Bool FBDevScreenInit(ScreenPtr pScreen, int argc, char **argv);
75 static Bool FBDevEnterVT(ScrnInfoPtr pScrn);
76 static void FBDevLeaveVT(ScrnInfoPtr pScrn);
77 static Bool FBDevCloseScreen(ScreenPtr pScreen);
78 static void FBDevSaveCurrent(ScrnInfoPtr pScrn);
80 /* This DriverRec must be defined in the driver for Xserver to load this driver */
81 _X_EXPORT DriverRec FBDEV =
87 FBDevAvailableOptions,
93 /* Supported "chipsets" */
94 static SymTabRec FBDevChipsets[] =
99 /* Supported options */
106 static const OptionInfoRec FBDevOptions[] =
108 { OPTION_SWCURSOR, "swcursor", OPTV_BOOLEAN, {0}, FALSE },
109 { OPTION_FBDEV, "fbdev", OPTV_STRING, {0}, FALSE },
110 { -1, NULL, OPTV_NONE, {0}, FALSE }
113 /* -------------------------------------------------------------------- */
118 MODULESETUPPROTO(FBDevSetup);
120 static XF86ModuleVersionInfo FBDevVersRec =
126 XORG_VERSION_CURRENT,
127 PACKAGE_VERSION_MAJOR,
128 PACKAGE_VERSION_MINOR,
129 PACKAGE_VERSION_PATCHLEVEL,
131 ABI_VIDEODRV_VERSION,
136 _X_EXPORT XF86ModuleData emulfbModuleData = { &FBDevVersRec, FBDevSetup, NULL };
139 FBDevSetup(pointer module, pointer opts, int *errmaj, int *errmin)
141 static Bool setupDone = FALSE;
146 xf86AddDriver(&FBDEV, module, HaveDriverFuncs);
151 if (errmaj) *errmaj = LDR_ONCEONLY;
156 #endif /* XFree86LOADER */
159 FBDevGetRec(ScrnInfoPtr pScrn)
161 if (pScrn->driverPrivate != NULL)
164 pScrn->driverPrivate = xnfcalloc(sizeof(FBDevRec), 1);
169 FBDevFreeRec(ScrnInfoPtr pScrn)
171 if (pScrn->driverPrivate == NULL)
173 free(pScrn->driverPrivate);
174 pScrn->driverPrivate = NULL;
177 /* -------------------------------------------------------------------- */
179 static const OptionInfoRec *
180 FBDevAvailableOptions(int chipid, int busid)
186 FBDevIdentify(int flags)
188 xf86PrintChipsets(FBDEV_NAME, "driver for framebuffer", FBDevChipsets);
192 * Probing the device with the device node, this probing depend on the specific hw.
193 * This function just verify whether the display hw is avaliable or not.
196 FBDevHWProbe(struct pci_device * pPci, const char *device,char **namep)
198 return fbdevHWProbe(pPci, (char *)device,namep);
201 /* The purpose of this function is to identify all instances of hardware supported
202 * by the driver. The probe must find the active device sections that match the driver
203 * by calling xf86MatchDevice().
206 FBDevProbe(DriverPtr drv, int flags)
210 GDevPtr *devSections;
214 Bool foundScreen = FALSE;
215 const char * drv_name = "fbdev";
216 const char * module_name = "fbdevhw";
218 /* For now, just bail out for PROBE_DETECT. */
219 if (flags & PROBE_DETECT)
222 if ((numDevSections = xf86MatchDevice(FBDEV_DRIVER_NAME, &devSections)) <= 0)
225 if (!xf86LoadDrvSubModule (drv, module_name))
228 for (i = 0; i < numDevSections; i++)
230 dev = xf86FindOptionValue (devSections[i]->options, drv_name);
231 if (FBDevHWProbe(NULL,dev,NULL))
234 entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
235 pScrn = xf86ConfigFbEntity(pScrn,0,entity, NULL,NULL,NULL,NULL);
241 pScrn->driverVersion = FBDEV_VERSION;
242 pScrn->driverName = FBDEV_DRIVER_NAME;
243 pScrn->name = FBDEV_NAME;
244 pScrn->Probe = FBDevProbe;
245 pScrn->PreInit = FBDevPreInit;
246 pScrn->ScreenInit = FBDevScreenInit;
247 pScrn->SwitchMode = fbdevHWSwitchModeWeak();
248 pScrn->AdjustFrame = fbdevHWAdjustFrameWeak();
249 pScrn->EnterVT = FBDevEnterVT;
250 pScrn->LeaveVT = FBDevLeaveVT;
251 pScrn->ValidMode = fbdevHWValidModeWeak();
253 xf86DrvMsg(pScrn->scrnIndex, X_INFO
254 ,"using %s\n", dev ? dev : "default device");
264 * Return the default depth and bits per pixel.
265 * Determine the depth and the bpp supported by hw with the hw color format.
268 FBDevGetDefaultDepth(ScrnInfoPtr pScrn, int *bitsPerPixel)
272 /* finding out the valid default_depth */
273 defaultDepth = fbdevHWGetDepth(pScrn,bitsPerPixel);
275 /* the default depth is not more than 24 */
276 defaultDepth = ((*bitsPerPixel)==32)?24:*bitsPerPixel;
282 * Initialize the device Probing the device with the device node,
283 * this probing depend on the specific hw.
284 * This function just verify whether the display hw is avaliable or not.
287 FBDevHWInit(ScrnInfoPtr pScrn, struct pci_device *pPci, const char *device)
289 /* open device : open the framebuffer device */
290 if (!fbdevHWInit(pScrn, NULL, (char *)device))
299 * DeInitialize the hw
302 FBDevHWDeInit(ScrnInfoPtr pScrn)
304 /* close the fd of the fb device ??? */
310 * Check the driver option.
311 * Set the option flags to the driver private
314 FBDevCheckDriverOptions(ScrnInfoPtr pScrn)
316 FBDevPtr pFBDev = FBDEVPTR(pScrn);
319 if (xf86ReturnOptValBool(pFBDev->Options, OPTION_SWCURSOR, FALSE))
320 pFBDev->bSWCursorEnbled = TRUE;
326 * This is called before ScreenInit to probe the screen configuration.
327 * The main tasks to do in this funtion are probing, module loading, option handling,
328 * card mapping, and Crtcs setup.
331 FBDevPreInit(ScrnInfoPtr pScrn, int flags)
334 int default_depth, fbbpp;
336 Gamma defualt_gamma = {0.0, 0.0, 0.0};
337 rgb default_weight = { 0, 0, 0 };
339 const char * fb_name = "fbdev";
341 if (flags & PROBE_DETECT) return FALSE;
343 /* Check the number of entities, and fail if it isn't one. */
344 if (pScrn->numEntities != 1)
347 pScrn->monitor = pScrn->confScreen->monitor;
349 /* allocate private */
351 pFBDev = FBDEVPTR(pScrn);
353 pFBDev->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
355 /* can set the path with fbdev option */
356 path = xf86FindOptionValue(pFBDev->pEnt->device->options, fb_name);
359 if(!FBDevHWInit(pScrn,NULL,path))
361 xf86DrvMsg(pScrn->scrnIndex, X_Error
362 , "fail to initialize hardware\n");
366 /* finding out the valid default_depth */
367 default_depth = FBDevGetDefaultDepth(pScrn,&fbbpp);
369 /* set the depth and the bpp to pScrn */
370 flag24 = Support24bppFb | Support32bppFb;
371 if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, fbbpp, flag24))
373 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
374 , "fail to find the depth\n");
377 xf86PrintDepthBpp(pScrn); /* just print out the depth and the bpp */
380 if (!xf86SetWeight(pScrn, default_weight, default_weight))
382 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
383 , "fail to set the color weight of RGB\n");
387 /* visual init, make a TrueColor, -1 */
388 if (!xf86SetDefaultVisual(pScrn, -1))
390 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
391 , "fail to initialize the default visual\n");
396 if (!xf86SetGamma(pScrn,defualt_gamma))
398 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
399 , "fail to set the gamma\n");
403 pScrn->progClock = TRUE;
405 pScrn->chipset = "fbdev";
406 pScrn->videoRam = fbdevHWGetVidmem(pScrn);
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO
409 , "hardware: %s (video memory: %dkB)\n"
410 , fbdevHWGetName(pScrn)
411 , pScrn->videoRam/1024);
413 /* Collect all the option flags (fill in pScrn->options) */
414 xf86CollectOptions(pScrn, NULL);
417 * Process the options based on the information S5POptions.
418 * The results are written to pS5P->Options. If all the options
419 * processing is done within this fuction a local variable "options"
420 * can be used instead of pS5P->Options
422 if (!(pFBDev->Options = malloc(sizeof(FBDevOptions))))
424 memcpy(pFBDev->Options, FBDevOptions, sizeof(FBDevOptions));
425 xf86ProcessOptions(pScrn->scrnIndex, pFBDev->pEnt->device->options, pFBDev->Options);
427 /* Check with the driver options */
428 FBDevCheckDriverOptions(pScrn);
430 /* Set the Crtc, the default Output, and the current Mode */
431 xf86DrvMsg(pScrn->scrnIndex, X_INFO
432 , "checking modes against framebuffer device and creating crtc and ouput...\n");
433 if(!FBDevCrtcConfigInit(pScrn))
435 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
436 , "Fail to init the CrtcConfig\n");
439 FBDevSaveCurrent(pScrn);
441 /* TODO::soolim:: re-confirm this condition */
442 if(pScrn->currentMode->HDisplay == pFBDev->var.xres_virtual
443 && pScrn->currentMode->VDisplay <= pFBDev->var.yres_virtual)
445 pScrn->virtualX = pFBDev->var.xres_virtual;
446 pScrn->virtualY = pFBDev->var.yres_virtual;
450 pScrn->virtualX = pScrn->currentMode->HDisplay;
451 pScrn->virtualY = pScrn->currentMode->VDisplay;
453 pScrn->displayWidth = pScrn->virtualX;
454 xf86PrintModes(pScrn); /* just print the current mode */
456 /* Set display resolution */
457 if(pFBDev->var.width && pFBDev->var.height)
459 pScrn->monitor->widthmm = pFBDev->var.width;
460 pScrn->monitor->heightmm = pFBDev->var.height;
462 xf86SetDpi(pScrn, 0, 0);
464 /* Load fb submodule */
465 if (!xf86LoadSubModule(pScrn, "fb"))
467 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to load fb module\n");
475 FBDevHWDeInit(pScrn);
480 FBDevAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
482 fbdevHWAdjustFrame(pScrn, x, y);
486 /* Save the hw information */
488 FBDevSave(ScrnInfoPtr pScrn)
490 FBDevPtr pFBDev = FBDEVPTR(pScrn);
492 FBDevGetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->saved_var);
495 /* Restore the hw information */
497 FBDevRestore(ScrnInfoPtr pScrn)
499 FBDevPtr pFBDev = FBDEVPTR(pScrn);
501 FBDevSetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->saved_var);
504 /* Save the current hw information */
506 FBDevSaveCurrent(ScrnInfoPtr pScrn)
508 FBDevPtr pFBDev = FBDEVPTR(pScrn);
510 FBDevGetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->var);
511 FBDevGetFixScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->fix);
515 FBDevModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
517 if (!fbdevHWModeInit(pScrn, mode))
523 /* Get the address of the framebuffer */
524 static unsigned char *
525 FBDevGetFbAddr(ScrnInfoPtr pScrn)
527 FBDevPtr pFBDev = FBDEVPTR(pScrn);
528 return pFBDev->fbstart;
532 FBDevScreenInit(ScreenPtr pScreen, int argc, char **argv)
534 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
535 FBDevPtr pFBDev = FBDEVPTR(pScrn);
537 int init_picture = 0;
538 unsigned char * pFbAddr;
539 pFBDev->rotate = RR_Rotate_0;
540 Bool rotated = (pFBDev->rotate & (RR_Rotate_90|RR_Rotate_270)) != 0;
542 xf86DrvMsg(pScrn->scrnIndex,X_INFO,
543 "Infomation of Visual is \n\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
544 "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
547 xf86GetVisualName(pScrn->defaultVisual),
548 (unsigned int) pScrn->mask.red,
549 (unsigned int) pScrn->mask.green,
550 (unsigned int) pScrn->mask.blue,
551 (int)pScrn->offset.red,
552 (int)pScrn->offset.green,
553 (int)pScrn->offset.blue);
555 pFBDev->fbmem = fbdevHWMapVidmem(pScrn); /* mmap memory pointer */
558 xf86DrvMsg(pScrn->scrnIndex,X_ERROR
559 ,"mapping of video memory failed\n");
562 pFBDev->fboff = fbdevHWLinearOffset(pScrn);
564 /* save fb information */
567 /* set mode and set fb info */
568 DisplayModePtr tmpMode;
571 tmpMode = &pFBDev->builtin_saved;
573 tmpMode = pScrn->currentMode;
575 if (!FBDevModeInit(pScrn, tmpMode))
577 xf86DrvMsg(pScrn->scrnIndex,X_ERROR
578 ,"mode initialization failed\n");
582 fbdevHWSaveScreen(pScreen, SCREEN_SAVER_ON);
583 FBDevAdjustFrame(pScrn,0,0);
585 FBDevSaveCurrent(pScrn);
588 miClearVisualTypes();
589 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor))
591 xf86DrvMsg(pScrn->scrnIndex,X_ERROR
592 ,"visual type setup failed for %d bits per pixel [1]\n"
593 , pScrn->bitsPerPixel);
596 if (!miSetPixmapDepths())
598 xf86DrvMsg(pScrn->scrnIndex,X_ERROR
599 ,"pixmap depth setup failed\n");
603 /* set the starting point of the framebuffer */
604 pFBDev->fbstart = pFBDev->fbmem + pFBDev->fboff;
606 /* Get the screen address */
607 pFbAddr = FBDevGetFbAddr(pScrn);
609 switch (pScrn->bitsPerPixel)
614 if(! fbScreenInit(pScreen, pFbAddr,
615 pScrn->virtualX, pScrn->virtualY,
616 pScrn->xDpi, pScrn->yDpi,
617 pScrn->virtualX, /*Pixel width for framebuffer*/
618 pScrn->bitsPerPixel))
625 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
626 , "internal error: invalid number of bits per pixel (%d) encountered\n"
627 , pScrn->bitsPerPixel);
631 if (pScrn->bitsPerPixel > 8)
633 /* Fixup RGB ordering */
634 visual = pScreen->visuals + pScreen->numVisuals;
635 while (--visual >= pScreen->visuals)
637 if ((visual->class | DynamicClass) == DirectColor)
639 visual->offsetRed = pScrn->offset.red;
640 visual->offsetGreen = pScrn->offset.green;
641 visual->offsetBlue = pScrn->offset.blue;
642 visual->redMask = pScrn->mask.red;
643 visual->greenMask = pScrn->mask.green;
644 visual->blueMask = pScrn->mask.blue;
649 /* must be after RGB ordering fixed */
650 if (init_picture && !fbPictureInit(pScreen, NULL, 0))
651 xf86DrvMsg(pScrn->scrnIndex, X_WARNING
652 , "Render extension initialisation failed\n");
654 /* XVideo Initiailization here */
656 if (!fbdevVideoInit(pScreen))
657 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
658 "XVideo extention initialization failed\n");
661 xf86SetBlackWhitePixels(pScreen);
662 miInitializeBackingStore(pScreen);
663 xf86SetBackingStore(pScreen);
665 /* Check whether the SWCURSOR option is enbled */
666 if(pFBDev->bSWCursorEnbled)
668 /* use software cursor */
669 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
673 /* use dummy hw_cursro instead of sw_cursor */
674 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
675 xf86DrvMsg(pScrn->scrnIndex, X_INFO
676 , "Initializing HW Cursor\n");
678 if(!xf86_cursors_init(pScreen, SEC_CURSOR_W, SEC_CURSOR_H, (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
679 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
680 HARDWARE_CURSOR_INVERT_MASK |
681 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
682 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
683 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
684 HARDWARE_CURSOR_ARGB)))
686 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
687 , "Hardware cursor initialization failed\n");
692 if (!xf86CrtcScreenInit(pScreen))
695 /* set the desire mode : set the mode to xf86crtc here */
696 xf86SetDesiredModes(pScrn);
699 if (!miCreateDefColormap(pScreen))
701 xf86DrvMsg(pScrn->scrnIndex, X_ERROR
702 , "internal error: miCreateDefColormap failed \n");
706 if(!xf86HandleColormaps(pScreen, 256, 8, fbdevHWLoadPaletteWeak(), NULL, CMAP_PALETTED_TRUECOLOR))
709 xf86DPMSInit(pScreen, FBDevDPMSSet(), 0);
710 pScreen->SaveScreen = FBDevSaveScreen();
711 pFBDev->isLcdOff = FALSE;
713 /* Wrap the current CloseScreen function */
714 pFBDev->CloseScreen = pScreen->CloseScreen;
715 pScreen->CloseScreen = FBDevCloseScreen;
717 /* register the event hook */
718 fbdevTraceInstallHooks ();
721 xDbgLogPListInit (pScreen);
729 FBDevEnterVT(ScrnInfoPtr pScrn)
731 xf86DrvMsg(pScrn->scrnIndex, X_INFO
732 , "EnterVT::Hardware state at EnterVT:\n");
737 FBDevLeaveVT(ScrnInfoPtr pScrn)
739 xf86DrvMsg(pScrn->scrnIndex, X_INFO
740 , "LeaveVT::Hardware state at LeaveVT:\n");
744 FBDevCloseScreen(ScreenPtr pScreen)
746 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
747 FBDevPtr pFBDev = FBDEVPTR(pScrn);
749 fbdevTraceUninstallHooks ();
753 fbdevHWUnmapVidmem(pScrn);
754 pScrn->vtSema = FALSE;
756 if(!pFBDev->bLockScreen)
759 ErrorF("Screen closed but LCD was locked\n");
761 FBDevHWDeInit(pScrn);
763 pScreen->CreateScreenResources = pFBDev->CreateScreenResources;
764 pScreen->CloseScreen = pFBDev->CloseScreen;
766 return (*pScreen->CloseScreen)(pScreen);