Files
xf86-video-freedreno/src/msm-driver.c
Enrico Weigelt, metux IT consult 6328da80ce replace obsolete "pointer" typedef by plain void*
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2026-01-05 18:22:11 +01:00

844 lines
20 KiB
C

/* msm-driver.c
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <string.h>
#include <sys/types.h>
#include <grp.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdint.h>
#include "xf86.h"
#include "damage.h"
#include "xf86_OSlib.h"
#include "xf86Crtc.h"
#include "mipointer.h"
#include "micmap.h"
#include "fb.h"
#include "dixstruct.h"
#include "msm.h"
#include "msm-accel.h"
#include <drm.h>
#include "xf86drm.h"
#define MSM_NAME "freedreno"
#define MSM_DRIVER_NAME "freedreno"
#define MSM_VERSION_MAJOR PACKAGE_VERSION_MAJOR
#define MSM_VERSION_MINOR PACKAGE_VERSION_MINOR
#define MSM_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
#define MSM_VERSION_CURRENT \
((MSM_VERSION_MAJOR << 20) |\
(MSM_VERSION_MINOR << 10) | \
(MSM_VERSION_PATCH))
/* An aray containing the options that the user can
configure in xorg.conf
*/
static const OptionInfoRec MSMOptions[] = {
{OPTION_FB, "fb", OPTV_STRING, {0}, FALSE},
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_EXAMASK, "examask", OPTV_INTEGER, {0}, FALSE},
{OPTION_SWREFRESHER, "SWRefresher", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_VSYNC, "DefaultVsync", OPTV_INTEGER, {0}, FALSE},
{OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
static Bool MSMEnterVT(ScrnInfoPtr pScrn);
static void MSMLeaveVT(ScrnInfoPtr pScrn);
Bool msmDebug = TRUE;
static void
MSMBlockHandler (ScreenPtr pScreen, void *pTimeout)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
MSMPtr pMsm = MSMPTR(pScrn);
pScreen->BlockHandler = pMsm->BlockHandler;
pScreen->BlockHandler(pScreen, pTimeout);
pScreen->BlockHandler = MSMBlockHandler;
if (pScrn->vtSema)
MSMFlushAccel(pScreen);
}
/*
* Because we don't use DRI1:
*/
static int
dri_drm_debug_print(const char *format, va_list ap)
{
xf86VDrvMsgVerb(-1, X_NONE, 3, format, ap);
return 0;
}
static void
dri_drm_get_perms(gid_t * group, mode_t * mode)
{
*group = -1;
*mode = 0666;
}
static drmServerInfo drm_server_info = {
dri_drm_debug_print,
xf86LoadKernelModule,
dri_drm_get_perms,
};
static void
free_msm(MSMPtr pMsm)
{
if (pMsm->drmFD)
#ifdef XF86_PDEV_SERVER_FD
if (!(pMsm->pEnt->location.type == BUS_PLATFORM &&
(pMsm->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
#endif
drmClose(pMsm->drmFD);
free(pMsm);
}
static Bool
MSMInitDRM(ScrnInfoPtr pScrn)
{
MSMPtr pMsm = MSMPTR(pScrn);
drmSetServerInfo(&drm_server_info);
pMsm->NoKMS = FALSE;
pMsm->drmFD = drmOpen("msm", NULL);
if (pMsm->drmFD < 0) {
pMsm->drmFD = drmOpen("kgsl", NULL);
pMsm->NoKMS = TRUE;
}
if (pMsm->drmFD < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Unable to open a DRM device\n");
return FALSE;
}
pMsm->dev = fd_device_new(pMsm->drmFD);
pMsm->deviceName = drmGetDeviceNameFromFd(pMsm->drmFD);
return TRUE;
}
/* This is the main initialization function for the screen */
static Bool
MSMPreInit(ScrnInfoPtr pScrn, int flags)
{
MSMPtr pMsm;
rgb defaultWeight = { 0, 0, 0 };
Gamma zeros = { 0.0, 0.0, 0.0 };
unsigned long val;
DEBUG_MSG("pre-init");
/* Omit ourselves from auto-probing (which is bound to
* fail on our hardware anyway)
*
* TODO we could probe for drm device..
*/
if (flags & PROBE_DETECT) {
DEBUG_MSG("probe not supported");
return FALSE;
}
if (pScrn->numEntities != 1) {
DEBUG_MSG("numEntities=%d", pScrn->numEntities);
return FALSE;
}
/* Just use the current monitor specified in the
* xorg.conf. This really means little to us since
* we have no choice over which monitor is used,
* but X needs this to be set
*/
pScrn->monitor = pScrn->confScreen->monitor;
/* Allocate room for our private data */
if (pScrn->driverPrivate == NULL)
pScrn->driverPrivate = XNFcallocarray(sizeof(MSMRec), 1);
pMsm = MSMPTR(pScrn);
if (pMsm == NULL) {
ERROR_MSG("Unable to allocate memory");
return FALSE;
}
xf86PrintDepthBpp(pScrn);
pScrn->rgbBits = 8;
pScrn->progClock = TRUE;
pScrn->chipset = MSM_DRIVER_NAME;
INFO_MSG("MSM/Qualcomm processor");
pMsm->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (!MSMInitDRM(pScrn)) {
ERROR_MSG("Unable to open DRM");
return FALSE;
}
if (pMsm->NoKMS) {
if (!fbmode_pre_init(pScrn)) {
ERROR_MSG("fbdev modesetting failed to initialize");
return FALSE;
}
} else {
if (!drmmode_pre_init(pScrn, pMsm->drmFD, pScrn->bitsPerPixel >> 3)) {
ERROR_MSG("Kernel modesetting failed to initialize");
return FALSE;
}
}
xf86CollectOptions(pScrn, NULL);
pMsm->options = malloc(sizeof(MSMOptions));
if (pMsm->options == NULL) {
free_msm(pMsm);
return FALSE;
}
memcpy(pMsm->options, MSMOptions, sizeof(MSMOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMsm->options);
/* Determine if the user wants debug messages turned on: */
msmDebug = xf86ReturnOptValBool(pMsm->options, OPTION_DEBUG, FALSE);
/* NoAccel - default FALSE */
pMsm->NoAccel = xf86ReturnOptValBool(pMsm->options, OPTION_NOACCEL, FALSE);
/* SWCursor - default FALSE */
pMsm->HWCursor = !xf86ReturnOptValBool(pMsm->options, OPTION_SWCURSOR, FALSE);
/* SWRefresher - default TRUE */
pMsm->SWRefresher = xf86ReturnOptValBool(pMsm->options, OPTION_SWREFRESHER, TRUE);
if (xf86GetOptValULong(pMsm->options, OPTION_EXAMASK, &val))
pMsm->examask = val;
else
pMsm->examask = ACCEL_DEFAULT;
INFO_MSG("Option Summary:");
INFO_MSG(" NoAccel: %d", pMsm->NoAccel);
INFO_MSG(" HWCursor: %d", pMsm->HWCursor);
INFO_MSG(" examask: %d", pMsm->examask);
if (pMsm->NoKMS) {
const char *fb = xf86GetOptValString(pMsm->options, OPTION_FB);
INFO_MSG(" fb: %s", fb);
INFO_MSG(" SWRefresher: %d", pMsm->SWRefresher);
}
INFO_MSG(" Debug: %d", msmDebug);
xf86PrintModes(pScrn);
/* FIXME: We will probably need to be more exact when setting
* the DPI. For now, we just use the default (96,96 I think) */
xf86SetDpi(pScrn, 0, 0);
if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) {
free_msm(pMsm);
return FALSE;
}
/* Initialize default visual */
if (!xf86SetDefaultVisual(pScrn, -1)) {
free_msm(pMsm);
return FALSE;
}
if (!xf86SetGamma(pScrn, zeros)) {
free_msm(pMsm);
return FALSE;
}
INFO_MSG("MSM Options:");
INFO_MSG(" HW Cursor: %s", pMsm->HWCursor ? "Enabled" : "Disabled");
return TRUE;
}
static Bool
MSMSaveScreen(ScreenPtr pScreen, int mode)
{
/* Nothing to do here, yet */
return TRUE;
}
static Bool
MSMCreateScreenResources(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
MSMPtr pMsm = MSMPTR(pScrn);
PixmapPtr ppix;
pScreen->CreateScreenResources = pMsm->CreateScreenResources;
if (!(*pScreen->CreateScreenResources)(pScreen))
return FALSE;
pScreen->CreateScreenResources = MSMCreateScreenResources;
if (!MSMEnterVT(NULL))
return FALSE;
ppix = pScreen->GetScreenPixmap(pScreen);
if (ppix) {
int pitch = MSMAlignedStride(ppix->drawable.width,
ppix->drawable.bitsPerPixel);
pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width,
ppix->drawable.height, ppix->drawable.depth,
ppix->drawable.bitsPerPixel, pitch, NULL);
msm_set_pixmap_bo(ppix, pMsm->scanout);
}
return TRUE;
}
static Bool
MSMCloseScreen(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
MSMPtr pMsm = MSMPTR(pScrn);
DEBUG_MSG("close screen");
MSMAccelFini(pScreen);
if (pScrn->vtSema) {
MSMLeaveVT(NULL);
pScrn->vtSema = FALSE;
}
if (pMsm->NoKMS) {
fbmode_screen_fini(pScreen);
} else {
drmmode_screen_fini(pScreen);
}
pScreen->BlockHandler = pMsm->BlockHandler;
pScreen->CloseScreen = pMsm->CloseScreen;
return (*pScreen->CloseScreen)(pScreen);
}
static Bool
MSMScreenInit(ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
MSMPtr pMsm = MSMPTR(pScrn);
int displayWidth;
DEBUG_MSG("screen-init");
/* Set up the X visuals */
miClearVisualTypes();
/* We only support TrueColor at the moment, and I suspect that is all
* we will ever support */
if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
pScrn->rgbBits, TrueColor)) {
ERROR_MSG("Unable to set up the visual for %d BPP", pScrn->bitsPerPixel);
return FALSE;
}
if (!miSetPixmapDepths()) {
ERROR_MSG("Unable to set the pixmap depth");
return FALSE;
}
/* Set up the X drawing area */
displayWidth = pScrn->displayWidth;
if (!displayWidth)
displayWidth = pScrn->virtualX;
xf86LoadSubModule(pScrn, "fb");
if (!fbScreenInit(pScreen, NULL,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi,
displayWidth, pScrn->bitsPerPixel)) {
ERROR_MSG("fbScreenInit failed");
return FALSE;
}
/* Set up the color information for the visual(s) */
if (pScrn->bitsPerPixel > 8) {
VisualPtr 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;
}
}
}
/* Set up the Render fallbacks */
if (!fbPictureInit(pScreen, NULL, 0)) {
ERROR_MSG("fbPictureInit failed");
return FALSE;
}
/* Set default colors */
xf86SetBlackWhitePixels(pScreen);
/* Set up the backing store */
xf86SetBackingStore(pScreen);
/* Set up EXA */
xf86LoadSubModule(pScrn, "exa");
if (!MSMAccelInit(pScreen))
ERROR_MSG("Unable to setup EXA");
/* Set up the software cursor */
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
/* Try to set up the HW cursor */
if (pMsm->HWCursor) {
if (pMsm->NoKMS)
pMsm->HWCursor = fbmode_cursor_init(pScreen);
else
pMsm->HWCursor = drmmode_cursor_init(pScreen);
if (!pMsm->HWCursor)
ERROR_MSG("Hardware cursor initialization failed");
}
/* Set up the default colormap */
if (!miCreateDefColormap(pScreen)) {
ERROR_MSG("miCreateDefColormap failed");
return FALSE;
}
pScreen->SaveScreen = MSMSaveScreen;
pMsm->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = MSMCloseScreen;
pMsm->CreateScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = MSMCreateScreenResources;
pMsm->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = MSMBlockHandler;
if (!xf86CrtcScreenInit(pScreen)) {
ERROR_MSG("CRTCScreenInit failed");
return FALSE;
}
if (pMsm->NoKMS) {
if (!fbmode_screen_init(pScreen)) {
ERROR_MSG("fbmode_screen_init failed");
return FALSE;
}
} else {
if (!drmmode_screen_init(pScreen)) {
ERROR_MSG("drmmode_screen_init failed");
return FALSE;
}
}
return TRUE;
}
static Bool
MSMSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
/* FIXME: We should only have the one mode, so we shouldn't ever call
* this function - regardless, it needs to be stubbed - so what
* do we return, TRUE or FALSE? */
return TRUE;
}
static Bool
MSMEnterVT(ScrnInfoPtr pScrn)
{
MSMPtr pMsm = MSMPTR(pScrn);
DEBUG_MSG("enter-vt");
if (!pMsm->NoKMS) {
int ret;
#ifdef XF86_PDEV_SERVER_FD
if (!(pMsm->pEnt->location.type == BUS_PLATFORM &&
(pMsm->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
ret = 0;
else
#endif
ret = drmSetMaster(pMsm->drmFD);
if (ret)
ERROR_MSG("Unable to get master: %s", strerror(errno));
}
/* Set up the mode - this doesn't actually touch the hardware,
* but it makes RandR all happy */
if (!xf86SetDesiredModes(pScrn)) {
ERROR_MSG("Unable to set the mode");
return FALSE;
}
return TRUE;
}
static void
MSMLeaveVT(ScrnInfoPtr pScrn)
{
MSMPtr pMsm = MSMPTR(pScrn);
DEBUG_MSG("leave-vt");
if (!pMsm->NoKMS) {
int ret;
#ifdef XF86_PDEV_SERVER_FD
if (!(pMsm->pEnt->location.type == BUS_PLATFORM &&
(pMsm->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
ret = 0;
else
#endif
ret = drmDropMaster(pMsm->drmFD);
if (ret)
ERROR_MSG("Unable to drop master: %s", strerror(errno));
}
}
static void
MSMFreeScreen(ScrnInfoPtr pScrn)
{
MSMPtr pMsm = MSMPTR(pScrn);
free_msm(pMsm);
}
/* ------------------------------------------------------------ */
/* Following is the standard driver setup that probes for the */
/* hardware and sets up the structures. */
static const OptionInfoRec *
MSMAvailableOptions(int chipid, int busid)
{
return MSMOptions;
}
static void
MSMIdentify(int flags)
{
xf86Msg(X_INFO, "%s: Video driver for Qualcomm processors\n", MSM_NAME);
}
static Bool
MSMProbe(DriverPtr drv, int flags)
{
GDevPtr *sections;
int i, nsects;
Bool foundScreen = FALSE;
ScrnInfoPtr pScrn = NULL;
/* For now, just return false during a probe */
if (flags & PROBE_DETECT) {
ErrorF("probe not supported\n");
return FALSE;
}
/* Find all of the device sections in the config */
nsects = xf86MatchDevice(MSM_NAME, &sections);
if (nsects <= 0) {
xf86Msg(X_INFO, "Did not find any matching device "
"section in configuration file\n");
if (flags & PROBE_DETECT) {
/* if we are probing, assume one and lets see if we can
* open the device to confirm it is there:
*/
nsects = 1;
} else {
return FALSE;
}
}
for (i = 0; i < nsects; i++) {
int entity, drmfd;
drmfd = drmOpen("msm", NULL);
if (drmfd < 0) {
const char *dev;
int fbdevfd;
xf86Msg(X_INFO, "No msm DRM/KMS, fallback to fbdev/kgsl\n");
/* ok, then legacy.. we need an fb too */
dev = xf86FindOptionValue(sections[i]->options, "fb");
xf86Msg(X_INFO, "Section %d - looking for %s\n", i, dev);
if (dev == NULL) {
xf86Msg(X_WARNING, "no device specified in section %d\n", i);
continue;
}
fbdevfd = open(dev, O_RDWR, 0);
if (fbdevfd < 0) {
xf86Msg(X_WARNING, "Could not open fbdev '%s': %s\n",
dev, strerror(errno));
continue;
}
close(fbdevfd);
drmfd = drmOpen("kgsl", NULL);
}
if (drmfd < 0) {
xf86Msg(X_WARNING, "Could not open drm: %s\n",
strerror(errno));
continue;
}
close(drmfd);
foundScreen = TRUE;
if (flags & PROBE_DETECT) {
/* just add the device.. we aren't a PCI device, so
* call xf86AddBusDeviceToConfigure() directly
*/
xf86AddBusDeviceToConfigure(MSM_DRIVER_NAME,
BUS_NONE, NULL, i);
continue;
}
entity = xf86ClaimFbSlot(drv, 0, sections[i], TRUE);
pScrn = xf86ConfigFbEntity(NULL, 0, entity, NULL, NULL, NULL, NULL);
/* Set up the hooks for the screen */
pScrn->driverVersion = MSM_VERSION_CURRENT;
pScrn->driverName = MSM_NAME;
pScrn->name = MSM_NAME;
pScrn->Probe = MSMProbe;
pScrn->PreInit = MSMPreInit;
pScrn->ScreenInit = MSMScreenInit;
pScrn->SwitchMode = MSMSwitchMode;
pScrn->EnterVT = MSMEnterVT;
pScrn->LeaveVT = MSMLeaveVT;
pScrn->FreeScreen = MSMFreeScreen;
}
free(sections);
return foundScreen;
}
static Bool
MSMDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
{
xorgHWFlags *flag;
switch (op) {
case GET_REQUIRED_HW_INTERFACES:
flag = (CARD32 *)data;
(*flag) = 0;
return TRUE;
#ifdef XF86_PDEV_SERVER_FD
case SUPPORTS_SERVER_FDS:
return TRUE;
#endif
default:
return FALSE;
}
}
#ifdef XSERVER_PLATFORM_BUS
static Bool probe_hw(struct xf86_platform_device *dev)
{
int fd;
/* NOTE: for kgsl we still need config file to find fbdev device,
* so it will always be probed through the old MSMProbe path. So
* only look for drm/msm here:
*/
#if XF86_PDEV_SERVER_FD
if (dev && (dev->flags & XF86_PDEV_SERVER_FD)) {
drmVersionPtr version;
fd = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_FD, -1);
if (fd == -1)
return FALSE;
version = drmGetVersion(fd);
/* make sure we have the right device: */
if (version && (strcmp(version->name, "msm") == 0)) {
drmFreeVersion(version);
return TRUE;
}
drmFreeVersion(version);
return FALSE;
}
#endif
fd = drmOpen("msm", NULL);
if (fd != -1) {
close(fd);
return TRUE;
}
return FALSE;
}
static Bool
MSMPlatformProbe(DriverPtr driver,
int entity_num, int flags, struct xf86_platform_device *dev,
intptr_t match_data)
{
ScrnInfoPtr pScrn = NULL;
int scr_flags = 0;
/* Note: at least for now there is no point in gpu screens.. and
* allowing them exposes a bug in older xservers that would result
* in the device probed as a gpu screen rather than regular screen
* resulting in "No screens found".
*
* If later there is actually reason to support GPU screens, track
* down the first xorg ABI # that contains the fix, and make this
* conditional on that or later ABI versions. Otherwise you will
* break things for people with older xservers.
*
if (flags & PLATFORM_PROBE_GPU_SCREEN)
scr_flags = XF86_ALLOCATE_GPU_SCREEN;
*/
if (probe_hw(dev)) {
pScrn = xf86AllocateScreen(driver, scr_flags);
xf86AddEntityToScreen(pScrn, entity_num);
pScrn->driverVersion = MSM_VERSION_CURRENT;
pScrn->driverName = MSM_NAME;
pScrn->name = MSM_NAME;
pScrn->Probe = MSMProbe;
pScrn->PreInit = MSMPreInit;
pScrn->ScreenInit = MSMScreenInit;
pScrn->SwitchMode = MSMSwitchMode;
pScrn->EnterVT = MSMEnterVT;
pScrn->LeaveVT = MSMLeaveVT;
pScrn->FreeScreen = MSMFreeScreen;
}
return pScrn != NULL;
}
#endif
_X_EXPORT DriverRec freedrenoDriver = {
MSM_VERSION_CURRENT,
MSM_DRIVER_NAME,
MSMIdentify,
MSMProbe,
MSMAvailableOptions,
NULL,
0,
MSMDriverFunc,
NULL,
NULL, /* pci_probe */
#ifdef XSERVER_PLATFORM_BUS
MSMPlatformProbe,
#endif
};
MODULESETUPPROTO(freedrenoSetup);
/* Versioning information for the module - most of these variables will
come from config.h generated by ./configure
*/
static XF86ModuleVersionInfo freedrenoVersRec = {
MSM_DRIVER_NAME,
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
MSM_VERSION_MAJOR, MSM_VERSION_MINOR, MSM_VERSION_PATCH,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
NULL,
{0, 0, 0, 0},
};
_X_EXPORT XF86ModuleData freedrenoModuleData = { &freedrenoVersRec, freedrenoSetup, NULL };
void *
freedrenoSetup(void *module, void *ops, int *errmaj, int *errmin)
{
static Bool initDone = FALSE;
if (initDone == FALSE) {
initDone = TRUE;
xf86AddDriver(&freedrenoDriver, module, HaveDriverFuncs);
/* FIXME: Load symbol references here */
return (void*) 1;
} else {
if (errmaj)
*errmaj = LDR_ONCEONLY;
return NULL;
}
}