diff options
Diffstat (limited to 'src/mali_fbdev.c')
-rw-r--r-- | src/mali_fbdev.c | 1196 |
1 files changed, 1196 insertions, 0 deletions
diff --git a/src/mali_fbdev.c b/src/mali_fbdev.c new file mode 100644 index 0000000..fecbd7e --- /dev/null +++ b/src/mali_fbdev.c @@ -0,0 +1,1196 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <linux/fb.h> + +#include "xf86.h" +#include "xf86cmap.h" +#include <xf86drm.h> +#include "xf86xv.h" +#include "xf86Crtc.h" +#include "micmap.h" + +#include "mali_def.h" +#include "mali_fbdev.h" +#include "exa.h" + +#define TRACE_ENTER(str) \ + do { if (1) ErrorF("mali: " str " %d\n",pScrn->scrnIndex); } while (0) +#define TRACE_EXIT(str) \ + do { if (1) ErrorF("mali: " str " done\n"); } while (0) +#define TRACE(str) \ + do { if (1) ErrorF("mali trace: " str "\n"); } while (0) +#define IGNORE( a ) ( a = a ); +#define PAGE_MASK (~(getpagesize() - 1)) +#define MALI_VERSION 4000 +#define MALI_NAME "MALI" +#define MALI_DRIVER_NAME "mali" + +static const OptionInfoRec * MaliAvailableOptions(int chipid, int busid); +static void MaliIdentify(int flags); +static Bool MaliProbe(DriverPtr drv, int flags); +static Bool MaliPreInit(ScrnInfoPtr pScrn, int flags); +static Bool MaliScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); +static Bool MaliCloseScreen(int scrnIndex, ScreenPtr pScreen); + +static int pix24bpp = 0; +static int malihwPrivateIndex = -1; + +static Bool debug = FALSE; + + +_X_EXPORT DriverRec MALI = { + MALI_VERSION, + MALI_DRIVER_NAME, + MaliIdentify, + MaliProbe, + MaliAvailableOptions, + NULL, + 0, + NULL, + NULL, + NULL, +}; + +/* Supported "chipsets" */ +static SymTabRec MaliChipsets[] = { + { 0, "mali" }, + {-1, NULL } +}; + +/* Supported options */ +typedef enum { + OPTION_DEBUG, + OPTION_DRI2, + OPTION_DRI2_PAGE_FLIP, + OPTION_DRI2_WAIT_VSYNC, +} FBDevOpts; + +static const OptionInfoRec MaliOptions[] = { + { OPTION_DEBUG, "debug", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DRI2, "DRI2", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_DRI2_PAGE_FLIP, "DRI2_PAGE_FLIP", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DRI2_WAIT_VSYNC, "DRI2_WAIT_VSYNC", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + + +#ifdef XFree86LOADER + +MODULESETUPPROTO(MaliSetup); + +static XF86ModuleVersionInfo MaliVersRec = +{ + "mali", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + NULL, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData maliModuleData = { &MaliVersRec, MaliSetup, NULL }; + +pointer MaliSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + TRACE("MaliSetup"); + + IGNORE(opts); + IGNORE(errmin); + + if (!setupDone) + { + setupDone = TRUE; + xf86AddDriver(&MALI, module, HaveDriverFuncs); + return (pointer)1; + } + else + { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ + + +static Bool MaliGetRec(ScrnInfoPtr pScrn) +{ + TRACE("MaliGetRec"); + + if (pScrn->driverPrivate != NULL) return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(MaliRec), 1); + + return TRUE; +} + +static void MaliFreeRec(ScrnInfoPtr pScrn) +{ + TRACE("MaliFreeRec"); + + if (pScrn->driverPrivate == NULL) return; + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +Bool MaliHWGetRec( ScrnInfoPtr pScrn ) +{ + MaliHWPtr fPtr; + + if ( malihwPrivateIndex < 0 ) malihwPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + + if ( MALIHWPTR(pScrn) != NULL ) return TRUE; + + fPtr = MALIHWPTRLVAL(pScrn) = xnfcalloc( sizeof(MaliHWRec), 1 ); + + return TRUE; +} + +void MaliHWFreeRec( ScrnInfoPtr pScrn ) +{ + if ( malihwPrivateIndex < 0 ) return; + + if ( MALIHWPTR( pScrn ) == NULL ) return; + + free( MALIHWPTR( pScrn ) ); + MALIHWPTRLVAL( pScrn ) = NULL; +} + +static const OptionInfoRec * MaliAvailableOptions(int chipid, int busid) +{ + TRACE("MaliAvailableOptions"); + IGNORE(chipid); + IGNORE(busid); + + return MaliOptions; +} + +static void MaliIdentify(int flags) +{ + TRACE("MaliIdentify"); + IGNORE(flags); + + xf86PrintChipsets(MALI_NAME, "driver for Mali Framebuffer", MaliChipsets); +} + +static Bool fbdev_crtc_config_resize( ScrnInfoPtr scrn, int width, int height ) +{ + xf86DrvMsg(scrn->scrnIndex, X_INFO, "%s: width = %d height = %d\n", __FUNCTION__, width, height); + + scrn->virtualX = width; + scrn->virtualY = height; + + return TRUE; +} + +static void mali_check_dri_options( ScrnInfoPtr pScrn ) +{ + MaliPtr fPtr = MALIPTR(pScrn); + + fPtr->dri_render = DRI_NONE; + + if ( !xf86ReturnOptValBool(fPtr->Options, OPTION_DRI2, TRUE) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI disabled. No support in config file\n"); + fPtr->dri_render = DRI_DISABLED; + } + + if ( xf86ReturnOptValBool(fPtr->Options, OPTION_DRI2_PAGE_FLIP, FALSE ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI Fullscreen page flip enabled\n"); + fPtr->use_pageflipping = TRUE; + } + else + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI Fullscreen page flip disabled. No support in config file\n"); + } + + if ( xf86ReturnOptValBool(fPtr->Options, OPTION_DRI2_WAIT_VSYNC, FALSE ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI Fullscreen page flip VSYNC'd\n"); + fPtr->use_pageflipping_vsync = TRUE; + } + else + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI Fullscreen page flip VSYNC disabled\n"); + } + + if ( pScrn->depth != 16 && pScrn->depth != 24 ) + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DRI is disabled since display does not run at 16bpp or 24bpp\n" ); + fPtr->dri_render = DRI_DISABLED; + } +} + +static void mali_check_exa_options( ScrnInfoPtr pScrn ) +{ + MaliPtr fPtr = MALIPTR(pScrn); + + IGNORE(fPtr); + + /* EXA specific options checked here */ +} + +static void mali_check_misc_options( ScrnInfoPtr pScrn ) +{ + MaliPtr fPtr = MALIPTR(pScrn); + + if ( xf86ReturnOptValBool(fPtr->Options, OPTION_DEBUG, FALSE ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, "DEBUG output enabled\n"); + debug = TRUE; + } +} + +static const xf86CrtcConfigFuncsRec fbdev_crtc_config_funcs = +{ + .resize = fbdev_crtc_config_resize, +}; + +static void FBDev_crtc_config( ScrnInfoPtr pScrn ) +{ + xf86CrtcConfigPtr xf86_config; + int max_width, max_height; + TRACE("FBDev_crtc_config"); + + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn, &fbdev_crtc_config_funcs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + max_width = 2048; + max_height = 2048; + + xf86CrtcSetSizeRange (pScrn, 640, 480, max_width, max_height); + TRACE_EXIT("FBDev_crtc_config"); +} + +static int mali_open( int scrnIndex, char *device, char **namep ) +{ + int fd; + struct fb_fix_screeninfo fix; + + + if ( device ) + { + fd = open( device, O_RDWR, 0 ); + } + else + { + device = getenv( "FRAMEBUFFER" ); + if ( ( NULL == device ) || ( ( fd = open(device, O_RDWR, 0 ) ) == -1 ) ) + { + device = "/dev/fb0"; + fd = open( device, O_RDWR, 0 ); + } + } + + if ( fd == -1 ) + { + xf86DrvMsg( scrnIndex, X_ERROR, "open %s: %s\n", device, strerror(errno) ); + return -1; + } + + if ( namep ) + { + if ( -1 == ioctl( fd, FBIOGET_FSCREENINFO, (void *)(&fix)) ) + { + *namep = NULL; + xf86DrvMsg( scrnIndex, X_ERROR, "FBIOGET_FSCREENINFO: %s\n", strerror( errno ) ); + return -1; + } + else + { + *namep = xnfalloc( 16 ); + strncpy( *namep, fix.id, 16 ); + } + } + + return fd; +} + +static void calculateFbmem_len(MaliHWPtr fPtr) +{ + fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; + fPtr->fbmem_len = (fPtr->fboff+fPtr->fix.smem_len+~PAGE_MASK) & PAGE_MASK; +} + +int MaliHWGetLineLength( ScrnInfoPtr pScrn ) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + TRACE("MaliHWGetLineLength"); + + if ( fPtr->fix.line_length ) return fPtr->fix.line_length; + + return fPtr->var.xres_virtual * fPtr->var.bits_per_pixel/8; +} + +void* MaliHWMapVidmem(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWMapVidmem"); + + if ( NULL == fPtr->fbmem ) + { + calculateFbmem_len( fPtr ); + fPtr->fbmem = mmap( NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fPtr->fd, 0 ); + if ( -1 == (long)fPtr->fbmem ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "mmap fbmem: %s\n", strerror(errno) ); + fPtr->fbmem = NULL; + } + else + { + } + } + + pScrn->memPhysBase = (unsigned long)fPtr->fix.smem_start & (unsigned long)(PAGE_MASK); + pScrn->fbOffset = (unsigned long)fPtr->fix.smem_start & (unsigned long)(~PAGE_MASK); + + return fPtr->fbmem; +} + +Bool MaliHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWSetMode"); + IGNORE(fPtr); + IGNORE(mode); + IGNORE(check); + + return TRUE; +} + +int MaliHWLinearOffset(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWLinearOffset"); + + return fPtr->fboff; +} + +Bool MaliHWUnmapVidmem(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWUnmapVidmem"); + if (NULL != fPtr->fbmem) + { + if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "munmap fbmem: %s\n", strerror(errno)); + fPtr->fbmem = NULL; + } + + return TRUE; +} + +Bool MaliHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWModeInit"); + + pScrn->vtSema = TRUE; + + if (!MaliHWSetMode(pScrn, mode, FALSE)) return FALSE; + + if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (pScrn->defaultVisual == TrueColor || pScrn->defaultVisual == DirectColor) + { + pScrn->offset.red = fPtr->var.red.offset; + pScrn->offset.green = fPtr->var.green.offset; + pScrn->offset.blue = fPtr->var.blue.offset; + pScrn->mask.red = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; + pScrn->mask.green = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; + pScrn->mask.blue = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; + } + + return TRUE; +} + +void MaliHWSave(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWSave"); + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->saved_var))) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); +} + +void MaliHWRestore(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWRestore"); + if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->saved_var))) xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); +} + +Bool MaliHWProbe( char *device, char **namep ) +{ + TRACE("MaliHWProbe"); + + if ( -1 == mali_open( -1, device, namep ) ) return FALSE; + + return TRUE; +} + +void MaliHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + struct fb_cmap cmap; + unsigned short red,green,blue; + int i; + + TRACE("MaliHWLoadPalette"); + IGNORE(pVisual); + + cmap.len = 1; + cmap.red = &red; + cmap.green = &green; + cmap.blue = &blue; + cmap.transp = NULL; + for (i = 0; i < numColors; i++) + { + cmap.start = indices[i]; + red = (colors[indices[i]].red << 8) | colors[indices[i]].red; + green = (colors[indices[i]].green << 8) | colors[indices[i]].green; + blue = (colors[indices[i]].blue << 8) | colors[indices[i]].blue; + if (-1 == ioctl(fPtr->fd,FBIOPUTCMAP,(void*)&cmap)) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOPUTCMAP: %s\n", strerror(errno)); + } +} + +Bool MaliHWSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MaliHWPtr fPtr = MALIHWPTR(pScrn); + unsigned long unblank; + + TRACE("MaliHWSaveScreen"); + + if (!pScrn->vtSema) return TRUE; + + unblank = xf86IsUnblank(mode); + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1-unblank))) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOBLANK: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +ModeStatus MaliHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE("MaliHWValidMode"); + IGNORE(verbose); + IGNORE(flags); + + if (!MaliHWSetMode(pScrn, mode, TRUE)) return MODE_BAD; + + return MODE_OK; +} + +Bool MaliHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE("MaliHWSwitchMode"); + IGNORE(flags); + + if (!MaliHWSetMode(pScrn, mode, FALSE)) return FALSE; + + return TRUE; +} + +void MaliHWAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWAdjustFrame"); + IGNORE(flags); + + if ( x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual ) return; + + fPtr->var.xoffset = x; + fPtr->var.yoffset = y; + if ( -1 == ioctl( fPtr->fd, FBIOPAN_DISPLAY, (void*)&fPtr->var) ) + { + xf86DrvMsgVerb(scrnIndex, X_WARNING, 5, "FBIOPAN_DISPLAY: %s\n", strerror(errno)); + } +} + +Bool MaliHWEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE("MaliHWEnterVT"); + IGNORE(flags); + + if (!MaliHWModeInit(pScrn, pScrn->currentMode)) return FALSE; + MaliHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return TRUE; +} + +void MaliHWLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE("MaliHWLeaveVT"); + IGNORE(flags); + + MaliHWRestore(pScrn); +} + +void MaliHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + unsigned long fbmode; + + TRACE("MaliHWDPMSSet"); + IGNORE(flags); + + if (!pScrn->vtSema) return; + + switch (mode) + { + case 0/*DPMSModeOn*/: + fbmode = 0; + break; + case 1/*DPMSModeStandby*/: + fbmode = 2; + break; + case 2/*DPMSModeSuspend*/: + fbmode = 3; + break; + case 3/*DPMSModeOff*/: + fbmode = 4; + break; + default: + return; + } + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOBLANK: %s\n", strerror(errno)); + } +} + +xf86SwitchModeProc *MaliHWSwitchModeWeak( void ) { return MaliHWSwitchMode; } +xf86AdjustFrameProc *MaliHWAdjustFrameWeak(void) { return MaliHWAdjustFrame; } +xf86EnterVTProc *MaliHWEnterVTWeak(void) { return MaliHWEnterVT; } +xf86LeaveVTProc *MaliHWLeaveVTWeak(void) { return MaliHWLeaveVT; } +xf86ValidModeProc *MaliHWValidModeWeak(void) { return MaliHWValidMode; } +xf86DPMSSetProc *MaliHWDPMSSetWeak(void) { return MaliHWDPMSSet; } +xf86LoadPaletteProc *MaliHWLoadPaletteWeak(void) { return MaliHWLoadPalette; } +SaveScreenProcPtr MaliHWSaveScreenWeak(void) { return MaliHWSaveScreen; } + + +static Bool MaliProbe( DriverPtr drv, int flags ) +{ + int i, numDevSections, entity; + Bool foundScreen = FALSE; + ScrnInfoPtr pScrn; + GDevPtr *devSections; + char *dev = "/dev/fb0"; + + TRACE("MaliProbe"); + + if (flags & PROBE_DETECT) return FALSE; + + if ((numDevSections = xf86MatchDevice(MALI_DRIVER_NAME, &devSections)) <= 0) return FALSE; + + for (i = 0; i < numDevSections; i++) + { + dev = xf86FindOptionValue( devSections[i]->options, "fbdev" ); + if ( MaliHWProbe( dev, NULL ) ) + { + pScrn = NULL; + entity = xf86ClaimFbSlot( drv, 0, devSections[i], TRUE ); + pScrn = xf86ConfigFbEntity( pScrn, 0, entity, NULL, NULL, NULL, NULL ); + if (pScrn) + { + foundScreen = TRUE; + + pScrn->driverVersion = MALI_VERSION; + pScrn->driverName = MALI_DRIVER_NAME; + pScrn->name = MALI_NAME; + pScrn->Probe = MaliProbe; + pScrn->PreInit = MaliPreInit; + pScrn->ScreenInit = MaliScreenInit; + + pScrn->SwitchMode = MaliHWSwitchModeWeak(); + pScrn->AdjustFrame = MaliHWAdjustFrameWeak(); + pScrn->EnterVT = MaliHWEnterVTWeak(); + pScrn->LeaveVT = MaliHWLeaveVTWeak(); + pScrn->ValidMode = MaliHWValidModeWeak(); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "using %s\n", dev ? dev : "default device"); + } + } + } + free(devSections); + + return foundScreen; +} + +Bool MaliHWInit( ScrnInfoPtr pScrn, char *device ) +{ + MaliHWPtr fPtr; + + TRACE("MaliHWInit"); + + MaliHWGetRec( pScrn ); + fPtr = MALIHWPTR( pScrn ); + fPtr->fd = mali_open( pScrn->scrnIndex,device,NULL ); + + if ( -1 == fPtr->fd ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "Failed to open framebuffer!\n" ); + return FALSE; + } + + if ( -1 == ioctl( fPtr->fd, FBIOGET_FSCREENINFO, (void *)(&fPtr->fix) ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "Failed to get fixed info!\n" ); + return FALSE; + } + + if ( -1 == ioctl( fPtr->fd, FBIOGET_VSCREENINFO, (void *)(&fPtr->var) ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "Failed to get var info!\n" ); + return FALSE; + } + + return TRUE; + +} + +int MaliHWGetDepth( ScrnInfoPtr pScrn, int *fbbpp ) +{ + MaliHWPtr fPtr = MALIHWPTR( pScrn ); + + TRACE("MaliHWGetDepth"); + + if ( fbbpp ) *fbbpp = fPtr->var.bits_per_pixel; + + if ( fPtr->fix.visual == FB_VISUAL_TRUECOLOR || fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR ) + { + return fPtr->var.red.length + fPtr->var.green.length + fPtr->var.blue.length; + } + + return fPtr->var.bits_per_pixel; +} + +int MaliHWGetVidmem( ScrnInfoPtr pScrn ) +{ + MaliHWPtr fPtr = MALIHWPTR( pScrn ); + TRACE("HWGetVidmem"); + + return fPtr->fix.smem_len; +} + +char *MaliHWGetName( ScrnInfoPtr pScrn ) +{ + MaliHWPtr fPtr = MALIHWPTR( pScrn ); + TRACE("MaliHWGetName"); + + return fPtr->fix.id; +} + +int MaliHWGetFD( ScrnInfoPtr pScrn ) +{ + MaliHWPtr fPtr; + TRACE("MaliHWGetFD"); + + MaliHWGetRec(pScrn); + fPtr = MALIHWPTR(pScrn); + + return fPtr->fd; +} + +void MaliHWSetVideoModes(ScrnInfoPtr pScrn) +{ + char **modename; + DisplayModePtr mode, this, last = pScrn->modes; + + TRACE("MaliHWSetVideoModes"); + + if ( NULL == pScrn->display->modes ) return; + + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + + for (modename = pScrn->display->modes; *modename != NULL; modename++) + { + for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) + if (0 == strcmp(mode->name,*modename)) break; + if (NULL == mode) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tmode \"%s\" not found\n", *modename); + continue; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tmodename \"%s\" mode->name \"%s\"\n", *modename, mode->name); + if (!MaliHWSetMode(pScrn, mode, TRUE)) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tmode \"%s\" test failed\n", *modename); + continue; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tmode \"%s\" ok\n", *modename); + + if (pScrn->virtualX < mode->HDisplay) pScrn->virtualX = mode->HDisplay; + if (pScrn->virtualY < mode->VDisplay) pScrn->virtualY = mode->VDisplay; + + if (NULL == pScrn->modes) + { + this = pScrn->modes = xf86DuplicateMode(mode); + this->next = this; + this->prev = this; + } + else + { + this = xf86DuplicateMode(mode); + this->next = pScrn->modes; + this->prev = last; + last->next = this; + pScrn->modes->prev = this; + } + last = this; + } +} + +void MaliHWUseBuildinMode(ScrnInfoPtr pScrn) +{ + MaliHWPtr fPtr = MALIHWPTR(pScrn); + + TRACE("MaliHWUseBuildinMode"); + pScrn->modes = &fPtr->buildin; + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + if (pScrn->virtualX < fPtr->buildin.HDisplay) pScrn->virtualX = fPtr->buildin.HDisplay; + if (pScrn->virtualY < fPtr->buildin.VDisplay) pScrn->virtualY = fPtr->buildin.VDisplay; +} + +static void mali_drm_close_master( ScrnInfoPtr pScrn ) +{ + MaliPtr fPtr = MALIPTR(pScrn); + if ( fPtr && fPtr->drm_fd > 0 ) + { + + xf86DrvMsg( pScrn->scrnIndex, X_INFO, "closing DRM device\n"); + drmClose( fPtr->drm_fd ); + fPtr->drm_fd = -1; + } +} + +static Bool mali_drm_open_master( ScrnInfoPtr pScrn ) +{ + MaliPtr fPtr = MALIPTR(pScrn); + drmSetVersion sv; + int err; + + fPtr->drm_fd = drmOpen("mali_drm", NULL ); + if ( fPtr->drm_fd == -1 ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "%s Unable to open DRM: %s\n", __func__, strerror(errno)); + return FALSE; + } + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "%s DRM OPEN (fd: 0x%x)\n", __func__, fPtr->drm_fd ); + + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; + sv.drm_dd_minor = -1; + + err = drmSetInterfaceVersion( fPtr->drm_fd, &sv ); + if ( err != 0 ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "%s DRM failed to interface version\n", __func__ ); + drmClose( fPtr->drm_fd ); + fPtr->drm_fd = -1; + return FALSE; + } + + + return TRUE; +} + + +static Bool MaliPreInit(ScrnInfoPtr pScrn, int flags) +{ + MaliPtr fPtr; + int default_depth, fbbpp; + + TRACE("MaliPreInit"); + + if (flags & PROBE_DETECT) return FALSE; + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) return FALSE; + + pScrn->monitor = pScrn->confScreen->monitor; + + MaliGetRec(pScrn); + fPtr = MALIPTR(pScrn); + + fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + fPtr->dri_open = FALSE; + fPtr->dri_render = DRI_NONE; + fPtr->use_pageflipping = FALSE; + fPtr->use_pageflipping_vsync = FALSE; + + /* open device */ + if ( !MaliHWInit( pScrn, xf86FindOptionValue( fPtr->pEnt->device->options,"fbdev" ) ) ) return FALSE; + + default_depth = MaliHWGetDepth(pScrn,&fbbpp); + if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, fbbpp, Support24bppFb | Support32bppFb | SupportConvert32to24 | SupportConvert24to32)) return FALSE; + xf86PrintDepthBpp(pScrn); + + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* color weight */ + if (pScrn->depth > 8) + { + rgb zeros = { 0, 0, 0 }; + if (!xf86SetWeight(pScrn, zeros, zeros)) return FALSE; + } + + /* visual init */ + if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; + + /* We don't currently support DirectColor at > 8bpp */ + if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "requested default visual (%s) is not supported at depth %d\n", xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); + return FALSE; + } + + { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn,zeros)) + { + return FALSE; + } + } + + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + pScrn->chipset = "mali"; + pScrn->videoRam = MaliHWGetVidmem(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s (video memory: %dkB)\n", MaliHWGetName(pScrn), pScrn->videoRam/1024); + + /* handle options */ + xf86CollectOptions(pScrn, NULL); + if (!(fPtr->Options = malloc(sizeof(MaliOptions)))) return FALSE; + + memcpy(fPtr->Options, MaliOptions, sizeof(MaliOptions)); + xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options, fPtr->Options); + + mali_check_dri_options( pScrn ); + + if ( fPtr->dri_render == DRI_NONE && FALSE == mali_drm_open_master( pScrn ) ) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to be master of DRM!\n"); + return FALSE; + } + + mali_check_dri_options( pScrn ); + mali_check_exa_options( pScrn ); + mali_check_misc_options( pScrn ); + + + fPtr->fb_lcd_fd = MaliHWGetFD( pScrn ); + + if ( ioctl( fPtr->fb_lcd_fd, FBIOGET_FSCREENINFO, &fPtr->fb_lcd_fix ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "FBIOGET_FSCREENINFO failed!\n" ); + return FALSE; + } + + if ( ioctl( fPtr->fb_lcd_fd, FBIOGET_VSCREENINFO, &fPtr->fb_lcd_var ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "FBIOGET_VSCREENINFO failed!\n" ); + return FALSE; + } + + pScrn->frameX0 = 0; + pScrn->frameY0 = 0; + pScrn->frameX1 = fPtr->fb_lcd_var.xres; + pScrn->frameY1 = fPtr->fb_lcd_var.yres; + + FBDev_crtc_config( pScrn ); + + if ( !FBDEV_lcd_init( pScrn ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "FBDev_lcd_init failed!\n" ); + return FALSE; + } + + if ( !xf86InitialConfiguration( pScrn, TRUE ) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "xf86InitialConfiguration failed!\n" ); + return FALSE; + } + + pScrn->displayWidth = pScrn->virtualX; + + xf86PrintModes( pScrn ); + xf86SetDpi( pScrn, 0, 0 ); + + if ( xf86LoadSubModule( pScrn, "fb" ) == NULL ) + { + MaliFreeRec( pScrn ); + return FALSE; + } + + return TRUE; +} + + +static Bool MaliScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MaliPtr fPtr = MALIPTR(pScrn); + VisualPtr visual; + int init_picture = 0; + int ret, flags; + + TRACE("MaliScreenInit"); + IGNORE(argc); + IGNORE(argv); + +#if DEBUG + ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n\tmask: %x,%x,%x, offset: %d,%d,%d\n", + pScrn->bitsPerPixel, + pScrn->depth, + xf86GetVisualName(pScrn->defaultVisual), + pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue, + pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue); +#endif + + if ( fPtr->dri_render == DRI_NONE ) + { + if ( TRUE == MaliDRI2ScreenInit( pScreen ) ) + { + fPtr->dri_render = DRI_2; + fPtr->dri_open = TRUE; + } + else xf86DrvMsg(scrnIndex,X_ERROR,"DRI2 initialization failed\n"); + } + + if (NULL == (fPtr->fbmem = MaliHWMapVidmem(pScrn))) + { + xf86DrvMsg(scrnIndex,X_ERROR,"mapping of video memory failed\n"); + return FALSE; + } + fPtr->fboff = MaliHWLinearOffset(pScrn); + + MaliHWSave(pScrn); + + if (!MaliHWModeInit(pScrn, pScrn->currentMode)) + { + xf86DrvMsg(scrnIndex,X_ERROR,"mode initialization failed\n"); + return FALSE; + } + MaliHWSaveScreen(pScreen, SCREEN_SAVER_ON); + MaliHWAdjustFrame(scrnIndex,0,0,0); + + /* mi layer */ + miClearVisualTypes(); + if (pScrn->bitsPerPixel > 8) + { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor)) + { + xf86DrvMsg(scrnIndex,X_ERROR,"visual type setup failed for %d bits per pixel [1]\n", pScrn->bitsPerPixel); + return FALSE; + } + } + else + { + if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) + { + xf86DrvMsg(scrnIndex,X_ERROR,"visual type setup failed for %d bits per pixel [2]\n", pScrn->bitsPerPixel); + return FALSE; + } + } + if (!miSetPixmapDepths()) + { + xf86DrvMsg(scrnIndex,X_ERROR,"pixmap depth setup failed\n"); + return FALSE; + } + + + fPtr->fbstart = fPtr->fbmem + fPtr->fboff; + + ret = fbScreenInit(pScreen, fPtr->fbstart, pScrn->virtualX, + pScrn->virtualY, pScrn->xDpi, + pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel); + init_picture = 1; + + if (pScrn->bitsPerPixel > 8) + { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) + { + if ((visual->class | DynamicClass) == DirectColor) + { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* must be after RGB ordering fixed */ + if (init_picture && !fbPictureInit(pScreen, NULL, 0)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Render extension initialisation failed\n"); + + xf86SetBlackWhitePixels(pScreen); + + xf86LoadSubModule(pScrn, "exa"); + fPtr->exa = exaDriverAlloc(); + + if ( maliSetupExa( pScreen, fPtr->exa, pScrn->virtualX, pScrn->virtualY, fPtr->fbmem ) ) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Initializing EXA Driver!\n"); + exaDriverInit( pScreen, fPtr->exa ); + } + else + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed allocating EXA Driver!\n"); + free( fPtr->exa ); + fPtr->exa = NULL; + } + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + /* software cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + xf86SetDesiredModes(pScrn); + + if ( !xf86CrtcScreenInit(pScreen) ) + { + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "xf86CrtcScreenInit failed\n"); + return FALSE; + } + + if (!miCreateDefColormap(pScreen)) + { + xf86DrvMsg(scrnIndex, X_ERROR, + "internal error: miCreateDefColormap failed in FBDevScreenInit()\n"); + return FALSE; + } + + flags = CMAP_PALETTED_TRUECOLOR; + + if(!xf86HandleColormaps(pScreen, 256, 8, MaliHWLoadPaletteWeak(), NULL, flags)) return FALSE; + + xf86DPMSInit(pScreen, MaliHWDPMSSetWeak(), 0); + + pScreen->SaveScreen = MaliHWSaveScreenWeak(); + + /* Wrap the current CloseScreen function */ + fPtr->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = MaliCloseScreen; + + { + XF86VideoAdaptorPtr *ptr; + + int n = xf86XVListGenericAdaptors(pScrn,&ptr); + if (n) xf86XVScreenInit(pScreen,ptr,n); + } + + return TRUE; +} + +static Bool MaliCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + MaliPtr fPtr = MALIPTR(pScrn); + TRACE("MaliCloseScreen"); + + MaliHWRestore(pScrn); + MaliHWUnmapVidmem(pScrn); + pScrn->vtSema = FALSE; + + pScreen->CreateScreenResources = fPtr->CreateScreenResources; + pScreen->CloseScreen = fPtr->CloseScreen; + + (*pScreen->CloseScreen)(scrnIndex, pScreen); + + if ( fPtr->dri_open && fPtr->dri_render == DRI_2 ) + { + fPtr->dri_open = FALSE; + MaliDRI2CloseScreen( pScreen ); + mali_drm_close_master( pScrn ); + } + + return TRUE; +} + |