2899 lines
78 KiB
C
2899 lines
78 KiB
C
|
|
/**************************************************************************
|
|
|
|
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
|
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, sub license, 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 (including the
|
|
next paragraph) 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 NON-INFRINGEMENT.
|
|
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
|
|
|
**************************************************************************/
|
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c,v 1.101 2004/01/02 20:15:47 dawes Exp $ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
/*
|
|
* Reformatted with GNU indent (2.2.8), using the following options:
|
|
*
|
|
* -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
|
|
* -lp -npcs -psl -sob -ss -br -ce -sc -hnl
|
|
*
|
|
* This provides a good match with the original i810 code and preferred
|
|
* XFree86 formatting conventions.
|
|
*
|
|
* When editing this driver, please follow the existing formatting, and edit
|
|
* with <TAB> characters expanded at 8-column intervals.
|
|
*/
|
|
|
|
/*
|
|
* Authors:
|
|
* Keith Whitwell <keith@tungstengraphics.com>
|
|
*
|
|
* Add ARGB HW cursor support:
|
|
* Alan Hourihane <alanh@tungstengraphics.com>
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* This server does not support these XFree86 4.0 features yet
|
|
* shadowFb (if requested or acceleration is off)
|
|
* Overlay planes
|
|
* DGA
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* These are X and server generic header files.
|
|
*/
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
#include "xf86Resources.h"
|
|
#include "xf86RAC.h"
|
|
#include "xf86cmap.h"
|
|
#include "compiler.h"
|
|
#include "mibstore.h"
|
|
#include "vgaHW.h"
|
|
#include "mipointer.h"
|
|
#include "micmap.h"
|
|
|
|
#include "fb.h"
|
|
#include "miscstruct.h"
|
|
#include "xf86xv.h"
|
|
#include <X11/extensions/Xv.h>
|
|
#include "vbe.h"
|
|
|
|
#include "i810.h"
|
|
#include "i830.h"
|
|
|
|
#ifdef XF86DRI
|
|
#include "dri.h"
|
|
#endif
|
|
|
|
/* Required Functions: */
|
|
|
|
static void I810Identify(int flags);
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
static Bool intel_pci_probe (DriverPtr drv,
|
|
int entity_num,
|
|
struct pci_device *dev,
|
|
intptr_t match_data);
|
|
#else
|
|
static Bool I810Probe(DriverPtr drv, int flags);
|
|
#endif
|
|
|
|
#ifndef I830_ONLY
|
|
static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
|
|
static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc,
|
|
char **argv);
|
|
static Bool I810EnterVT(int scrnIndex, int flags);
|
|
static void I810LeaveVT(int scrnIndex, int flags);
|
|
static Bool I810CloseScreen(int scrnIndex, ScreenPtr pScreen);
|
|
static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank);
|
|
static void I810FreeScreen(int scrnIndex, int flags);
|
|
static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn,
|
|
int PowerManagermentMode,
|
|
int flags);
|
|
static ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode,
|
|
Bool verbose, int flags);
|
|
#endif /* I830_ONLY */
|
|
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
|
|
#define INTEL_DEVICE_MATCH(d,i) \
|
|
{ 0x8086, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
|
|
|
|
static const struct pci_id_match intel_device_match[] = {
|
|
#ifndef I830_ONLY
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I810, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I810_DC100, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I810_E, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I815, 0 ),
|
|
#endif
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I830_M, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_845_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I855_GM, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I865_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I915_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_E7221_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I915_GM, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I945_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I945_GM, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I945_GME, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I965_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_G35_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I965_Q, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I946_GZ, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I965_GM, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_I965_GME, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_G33_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_Q35_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_Q33_G, 0 ),
|
|
INTEL_DEVICE_MATCH (PCI_CHIP_IGD_GM, 0 ),
|
|
{ 0, 0, 0 },
|
|
};
|
|
|
|
#endif /* XSERVER_LIBPCIACCESS */
|
|
|
|
_X_EXPORT DriverRec I810 = {
|
|
I810_VERSION,
|
|
I810_DRIVER_NAME,
|
|
I810Identify,
|
|
#if XSERVER_LIBPCIACCESS
|
|
NULL,
|
|
#else
|
|
I810Probe,
|
|
#endif
|
|
I810AvailableOptions,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
#if XSERVER_LIBPCIACCESS
|
|
intel_device_match,
|
|
intel_pci_probe
|
|
#endif
|
|
};
|
|
|
|
/* *INDENT-OFF* */
|
|
/* Chipsets */
|
|
static SymTabRec I810Chipsets[] = {
|
|
#ifndef I830_ONLY
|
|
{PCI_CHIP_I810, "i810"},
|
|
{PCI_CHIP_I810_DC100, "i810-dc100"},
|
|
{PCI_CHIP_I810_E, "i810e"},
|
|
{PCI_CHIP_I815, "i815"},
|
|
#endif
|
|
{PCI_CHIP_I830_M, "i830M"},
|
|
{PCI_CHIP_845_G, "845G"},
|
|
{PCI_CHIP_I855_GM, "852GM/855GM"},
|
|
{PCI_CHIP_I865_G, "865G"},
|
|
{PCI_CHIP_I915_G, "915G"},
|
|
{PCI_CHIP_E7221_G, "E7221 (i915)"},
|
|
{PCI_CHIP_I915_GM, "915GM"},
|
|
{PCI_CHIP_I945_G, "945G"},
|
|
{PCI_CHIP_I945_GM, "945GM"},
|
|
{PCI_CHIP_I945_GME, "945GME"},
|
|
{PCI_CHIP_I965_G, "965G"},
|
|
{PCI_CHIP_G35_G, "G35"},
|
|
{PCI_CHIP_I965_Q, "965Q"},
|
|
{PCI_CHIP_I946_GZ, "946GZ"},
|
|
{PCI_CHIP_I965_GM, "965GM"},
|
|
{PCI_CHIP_I965_GME, "965GME/GLE"},
|
|
{PCI_CHIP_G33_G, "G33"},
|
|
{PCI_CHIP_Q35_G, "Q35"},
|
|
{PCI_CHIP_Q33_G, "Q33"},
|
|
{PCI_CHIP_IGD_GM, "Intel Integrated Graphics Device"},
|
|
{-1, NULL}
|
|
};
|
|
|
|
static PciChipsets I810PciChipsets[] = {
|
|
#ifndef I830_ONLY
|
|
{PCI_CHIP_I810, PCI_CHIP_I810, RES_SHARED_VGA},
|
|
{PCI_CHIP_I810_DC100, PCI_CHIP_I810_DC100, RES_SHARED_VGA},
|
|
{PCI_CHIP_I810_E, PCI_CHIP_I810_E, RES_SHARED_VGA},
|
|
{PCI_CHIP_I815, PCI_CHIP_I815, RES_SHARED_VGA},
|
|
#endif
|
|
{PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA},
|
|
{PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA},
|
|
{PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA},
|
|
{PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA},
|
|
{PCI_CHIP_I945_GME, PCI_CHIP_I945_GME, RES_SHARED_VGA},
|
|
{PCI_CHIP_I965_G, PCI_CHIP_I965_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_G35_G, PCI_CHIP_G35_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_I965_Q, PCI_CHIP_I965_Q, RES_SHARED_VGA},
|
|
{PCI_CHIP_I946_GZ, PCI_CHIP_I946_GZ, RES_SHARED_VGA},
|
|
{PCI_CHIP_I965_GM, PCI_CHIP_I965_GM, RES_SHARED_VGA},
|
|
{PCI_CHIP_I965_GME, PCI_CHIP_I965_GME, RES_SHARED_VGA},
|
|
{PCI_CHIP_G33_G, PCI_CHIP_G33_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_Q35_G, PCI_CHIP_Q35_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_Q33_G, PCI_CHIP_Q33_G, RES_SHARED_VGA},
|
|
{PCI_CHIP_IGD_GM, PCI_CHIP_IGD_GM, RES_SHARED_VGA},
|
|
{-1, -1, RES_UNDEFINED }
|
|
};
|
|
|
|
#ifndef I830_ONLY
|
|
typedef enum {
|
|
OPTION_NOACCEL,
|
|
OPTION_SW_CURSOR,
|
|
OPTION_COLOR_KEY,
|
|
OPTION_CACHE_LINES,
|
|
OPTION_DAC_6BIT,
|
|
OPTION_DRI,
|
|
OPTION_NO_DDC,
|
|
OPTION_SHOW_CACHE,
|
|
OPTION_XVMC_SURFACES,
|
|
OPTION_PAGEFLIP
|
|
} I810Opts;
|
|
|
|
static const OptionInfoRec I810Options[] = {
|
|
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
|
|
{OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
|
|
{OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
|
|
{OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE},
|
|
{OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
|
|
{-1, NULL, OPTV_NONE, {0}, FALSE}
|
|
};
|
|
/* *INDENT-ON* */
|
|
#endif
|
|
|
|
const char *I810vgahwSymbols[] = {
|
|
"vgaHWFreeHWRec",
|
|
"vgaHWGetHWRec",
|
|
"vgaHWGetIOBase",
|
|
"vgaHWGetIndex",
|
|
"vgaHWInit",
|
|
"vgaHWLock",
|
|
"vgaHWMapMem",
|
|
"vgaHWProtect",
|
|
"vgaHWRestore",
|
|
"vgaHWSave",
|
|
"vgaHWSaveScreen",
|
|
"vgaHWSetMmioFuncs",
|
|
"vgaHWUnlock",
|
|
"vgaHWUnmapMem",
|
|
NULL
|
|
};
|
|
|
|
const char *I810fbSymbols[] = {
|
|
"fbPictureInit",
|
|
"fbScreenInit",
|
|
NULL
|
|
};
|
|
|
|
const char *I810vbeSymbols[] = {
|
|
"VBEFreeModeInfo",
|
|
"VBEFreeVBEInfo",
|
|
"VBEGetModeInfo",
|
|
"VBEGetModePool",
|
|
"VBEGetVBEInfo",
|
|
"VBEGetVBEMode",
|
|
"VBEInit",
|
|
"VBEPrintModes",
|
|
"VBESaveRestore",
|
|
"VBESetDisplayStart",
|
|
"VBESetGetDACPaletteFormat",
|
|
"VBESetGetLogicalScanlineLength",
|
|
"VBESetGetPaletteData",
|
|
"VBESetModeNames",
|
|
"VBESetModeParameters",
|
|
"VBESetVBEMode",
|
|
"VBEValidateModes",
|
|
"vbeDoEDID",
|
|
"vbeFree",
|
|
NULL
|
|
};
|
|
|
|
#ifdef XFree86LOADER
|
|
static const char *vbeOptionalSymbols[] = {
|
|
"VBEDPMSSet",
|
|
"VBEGetPixelClock",
|
|
NULL
|
|
};
|
|
#endif
|
|
|
|
const char *I810ddcSymbols[] = {
|
|
"xf86PrintEDID",
|
|
"xf86SetDDCproperties",
|
|
NULL
|
|
};
|
|
|
|
const char *I810int10Symbols[] = {
|
|
"xf86ExecX86int10",
|
|
"xf86InitInt10",
|
|
"xf86Int10AllocPages",
|
|
"xf86int10Addr",
|
|
NULL
|
|
};
|
|
|
|
const char *I810xaaSymbols[] = {
|
|
"XAACreateInfoRec",
|
|
"XAADestroyInfoRec",
|
|
"XAAInit",
|
|
"XAAGetCopyROP",
|
|
"XAAGetPatternROP",
|
|
NULL
|
|
};
|
|
|
|
const char *I810ramdacSymbols[] = {
|
|
"xf86CreateCursorInfoRec",
|
|
"xf86DestroyCursorInfoRec",
|
|
"xf86InitCursor",
|
|
NULL
|
|
};
|
|
|
|
const char *I810shadowFBSymbols[] = {
|
|
"ShadowFBInit",
|
|
NULL
|
|
};
|
|
|
|
#ifdef XF86DRI
|
|
const char *I810drmSymbols[] = {
|
|
"drmAddBufs",
|
|
"drmAddMap",
|
|
"drmAgpAcquire",
|
|
"drmAgpAlloc",
|
|
"drmAgpBind",
|
|
"drmAgpEnable",
|
|
"drmAgpFree",
|
|
"drmAgpRelease",
|
|
"drmAgpUnbind",
|
|
"drmAuthMagic",
|
|
"drmCommandNone",
|
|
"drmCommandWrite",
|
|
"drmCreateContext",
|
|
"drmCtlInstHandler",
|
|
"drmCtlUninstHandler",
|
|
"drmDestroyContext",
|
|
"drmFreeVersion",
|
|
"drmGetInterruptFromBusID",
|
|
"drmGetLibVersion",
|
|
"drmGetVersion",
|
|
"drmRmMap",
|
|
#ifdef XSERVER_LIBDRM_MM
|
|
"drmMMInit",
|
|
"drmMMTakedown",
|
|
"drmMMLock",
|
|
"drmMMUnlock",
|
|
#endif
|
|
NULL
|
|
};
|
|
|
|
|
|
const char *I810driSymbols[] = {
|
|
"DRICloseScreen",
|
|
"DRICreateInfoRec",
|
|
"DRIGetContext",
|
|
"DRIDestroyInfoRec",
|
|
"DRIFinishScreenInit",
|
|
"DRIGetSAREAPrivate",
|
|
"DRILock",
|
|
"DRIQueryVersion",
|
|
"DRIScreenInit",
|
|
"DRIUnlock",
|
|
"GlxSetVisualConfigs",
|
|
"DRICreatePCIBusID",
|
|
NULL
|
|
};
|
|
|
|
#endif /* I830_ONLY */
|
|
|
|
const char *I810i2cSymbols[] = {
|
|
"xf86CreateI2CBusRec",
|
|
"xf86I2CBusInit",
|
|
NULL
|
|
};
|
|
|
|
#ifndef I810_DEBUG
|
|
int I810_DEBUG = (0
|
|
/* | DEBUG_ALWAYS_SYNC */
|
|
/* | DEBUG_VERBOSE_ACCEL */
|
|
/* | DEBUG_VERBOSE_SYNC */
|
|
/* | DEBUG_VERBOSE_VGA */
|
|
/* | DEBUG_VERBOSE_RING */
|
|
/* | DEBUG_VERBOSE_OUTREG */
|
|
/* | DEBUG_VERBOSE_MEMORY */
|
|
/* | DEBUG_VERBOSE_CURSOR */
|
|
);
|
|
#endif
|
|
|
|
#ifndef I830_ONLY
|
|
#ifdef XF86DRI
|
|
static int i810_pitches[] = {
|
|
512,
|
|
1024,
|
|
2048,
|
|
4096,
|
|
0
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
int I830EntityIndex = -1;
|
|
|
|
#ifdef XFree86LOADER
|
|
|
|
static MODULESETUPPROTO(i810Setup);
|
|
|
|
static XF86ModuleVersionInfo intelVersRec = {
|
|
"intel",
|
|
MODULEVENDORSTRING,
|
|
MODINFOSTRING1,
|
|
MODINFOSTRING2,
|
|
XORG_VERSION_CURRENT,
|
|
INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH,
|
|
ABI_CLASS_VIDEODRV,
|
|
ABI_VIDEODRV_VERSION,
|
|
MOD_CLASS_VIDEODRV,
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
_X_EXPORT XF86ModuleData intelModuleData = { &intelVersRec, i810Setup, NULL };
|
|
|
|
static XF86ModuleVersionInfo i810VersRec = {
|
|
"i810",
|
|
MODULEVENDORSTRING,
|
|
MODINFOSTRING1,
|
|
MODINFOSTRING2,
|
|
XORG_VERSION_CURRENT,
|
|
INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH,
|
|
ABI_CLASS_VIDEODRV,
|
|
ABI_VIDEODRV_VERSION,
|
|
MOD_CLASS_VIDEODRV,
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
_X_EXPORT XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, NULL };
|
|
|
|
static pointer
|
|
i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = 0;
|
|
|
|
/* This module should be loaded only once, but check to be sure.
|
|
*/
|
|
if (!setupDone) {
|
|
setupDone = 1;
|
|
xf86AddDriver(&I810, module,
|
|
#if XSERVER_LIBPCIACCESS
|
|
HaveDriverFuncs
|
|
#else
|
|
0
|
|
#endif
|
|
);
|
|
|
|
/*
|
|
* Tell the loader about symbols from other modules that this module
|
|
* might refer to.
|
|
*/
|
|
LoaderRefSymLists(I810vgahwSymbols,
|
|
I810fbSymbols, I810xaaSymbols, I810ramdacSymbols,
|
|
#ifdef XF86DRI
|
|
I810drmSymbols,
|
|
I810driSymbols,
|
|
#endif
|
|
I810shadowFBSymbols,
|
|
I810vbeSymbols, vbeOptionalSymbols,
|
|
I810ddcSymbols, I810int10Symbols, NULL);
|
|
|
|
/*
|
|
* The return value must be non-NULL on success even though there
|
|
* is no TearDownProc.
|
|
*/
|
|
return (pointer) 1;
|
|
} else {
|
|
if (errmaj)
|
|
*errmaj = LDR_ONCEONLY;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef I830_ONLY
|
|
/*
|
|
* I810GetRec and I810FreeRec --
|
|
*
|
|
* Private data for the driver is stored in the screen structure.
|
|
* These two functions create and destroy that private data.
|
|
*
|
|
*/
|
|
static Bool
|
|
I810GetRec(ScrnInfoPtr pScrn)
|
|
{
|
|
if (pScrn->driverPrivate)
|
|
return TRUE;
|
|
|
|
pScrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
I810FreeRec(ScrnInfoPtr pScrn)
|
|
{
|
|
if (!pScrn)
|
|
return;
|
|
if (!pScrn->driverPrivate)
|
|
return;
|
|
xfree(pScrn->driverPrivate);
|
|
pScrn->driverPrivate = NULL;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* I810Identify --
|
|
*
|
|
* Returns the string name for the driver based on the chipset. In this
|
|
* case it will always be an I810, so we can return a static string.
|
|
*
|
|
*/
|
|
static void
|
|
I810Identify(int flags)
|
|
{
|
|
xf86PrintChipsets(I810_NAME, "Driver for Intel Integrated Graphics Chipsets",
|
|
I810Chipsets);
|
|
}
|
|
|
|
const OptionInfoRec *
|
|
I810AvailableOptions(int chipid, int busid)
|
|
{
|
|
#ifndef I830_ONLY
|
|
const OptionInfoRec *pOptions;
|
|
|
|
if ((pOptions = I830AvailableOptions(chipid, busid)))
|
|
return pOptions;
|
|
return I810Options;
|
|
#else
|
|
return I830AvailableOptions(chipid, busid);
|
|
#endif
|
|
}
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
struct pci_device *
|
|
intel_host_bridge (void)
|
|
{
|
|
static const struct pci_slot_match bridge_match = {
|
|
0, 0, 0, PCI_MATCH_ANY, 0
|
|
};
|
|
struct pci_device_iterator *slot_iterator;
|
|
struct pci_device *bridge;
|
|
|
|
slot_iterator = pci_slot_match_iterator_create (&bridge_match);
|
|
bridge = pci_device_next (slot_iterator);
|
|
pci_iterator_destroy (slot_iterator);
|
|
return bridge;
|
|
}
|
|
|
|
/*
|
|
* intel_pci_probe --
|
|
*
|
|
* Look through the PCI bus to find cards that are intel boards.
|
|
* Setup the dispatch table for the rest of the driver functions.
|
|
*
|
|
*/
|
|
static Bool intel_pci_probe (DriverPtr driver,
|
|
int entity_num,
|
|
struct pci_device *device,
|
|
intptr_t match_data)
|
|
{
|
|
ScrnInfoPtr scrn = NULL;
|
|
EntityInfoPtr entity;
|
|
I830EntPtr i830_ent = NULL;
|
|
DevUnion *private;
|
|
|
|
scrn = xf86ConfigPciEntity (scrn, 0, entity_num, I810PciChipsets,
|
|
NULL,
|
|
NULL, NULL, NULL, NULL);
|
|
if (scrn != NULL)
|
|
{
|
|
scrn->driverVersion = I810_VERSION;
|
|
scrn->driverName = I810_DRIVER_NAME;
|
|
scrn->name = I810_NAME;
|
|
scrn->Probe = NULL;
|
|
|
|
entity = xf86GetEntityInfo (entity_num);
|
|
|
|
switch (DEVICE_ID(device)) {
|
|
#ifndef I830_ONLY
|
|
case PCI_CHIP_I810:
|
|
case PCI_CHIP_I810_DC100:
|
|
case PCI_CHIP_I810_E:
|
|
case PCI_CHIP_I815:
|
|
scrn->PreInit = I810PreInit;
|
|
scrn->ScreenInit = I810ScreenInit;
|
|
scrn->SwitchMode = I810SwitchMode;
|
|
scrn->AdjustFrame = I810AdjustFrame;
|
|
scrn->EnterVT = I810EnterVT;
|
|
scrn->LeaveVT = I810LeaveVT;
|
|
scrn->FreeScreen = I810FreeScreen;
|
|
scrn->ValidMode = I810ValidMode;
|
|
break;
|
|
#endif
|
|
case PCI_CHIP_845_G:
|
|
case PCI_CHIP_I865_G:
|
|
/*
|
|
* These two chips have only one pipe, and
|
|
* cannot do dual-head
|
|
*/
|
|
I830InitpScrn(scrn);
|
|
break;
|
|
default:
|
|
/*
|
|
* Everything else is an i830-ish dual-pipe chip
|
|
*/
|
|
xf86SetEntitySharable(entity_num);
|
|
|
|
/* Allocate an entity private if necessary */
|
|
if (I830EntityIndex < 0)
|
|
I830EntityIndex = xf86AllocateEntityPrivateIndex();
|
|
|
|
private = xf86GetEntityPrivate(scrn->entityList[0],
|
|
I830EntityIndex);
|
|
i830_ent = private->ptr;
|
|
if (!i830_ent)
|
|
{
|
|
private->ptr = xnfcalloc(sizeof(I830EntRec), 1);
|
|
i830_ent = private->ptr;
|
|
i830_ent->lastInstance = -1;
|
|
}
|
|
|
|
/*
|
|
* Set the entity instance for this instance of the driver.
|
|
* For dual head per card, instance 0 is the "master"
|
|
* instance, driving the primary head, and instance 1 is
|
|
* the "slave".
|
|
*/
|
|
i830_ent->lastInstance++;
|
|
xf86SetEntityInstanceForScreen(scrn,
|
|
scrn->entityList[0],
|
|
i830_ent->lastInstance);
|
|
I830InitpScrn(scrn);
|
|
break;
|
|
}
|
|
}
|
|
return scrn != NULL;
|
|
}
|
|
#else /* XSERVER_LIBPCIACCESS */
|
|
|
|
/*
|
|
* I810Probe --
|
|
*
|
|
* Look through the PCI bus to find cards that are I810 boards.
|
|
* Setup the dispatch table for the rest of the driver functions.
|
|
*
|
|
*/
|
|
static Bool
|
|
I810Probe(DriverPtr drv, int flags)
|
|
{
|
|
int i, numUsed, numDevSections, *usedChips;
|
|
I830EntPtr pI830Ent = NULL;
|
|
DevUnion *pPriv;
|
|
GDevPtr *devSections;
|
|
Bool foundScreen = FALSE;
|
|
pciVideoPtr *VideoInfo;
|
|
pciVideoPtr *ppPci;
|
|
PciChipsets *id;
|
|
|
|
/*
|
|
* Find the config file Device sections that match this
|
|
* driver, and return if there are none.
|
|
*/
|
|
if ((numDevSections =
|
|
xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0 &&
|
|
(numDevSections =
|
|
xf86MatchDevice(I810_LEGACY_DRIVER_NAME, &devSections)) <= 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* This probing is just checking the PCI data the server already
|
|
* collected.
|
|
*/
|
|
if (!(VideoInfo = xf86GetPciVideoInfo()))
|
|
return FALSE;
|
|
|
|
/*
|
|
* Mobile platforms may have both function 0 and 1 active, but they
|
|
* are handled as a single entity. To make sure that the function 1
|
|
* entity isn't assigned to a screen, check for and claim it here
|
|
* first.
|
|
*
|
|
* XXX If function 1's resources are ever needed, they'll need to be
|
|
* added to the screen and marked active.
|
|
*/
|
|
for (ppPci = VideoInfo; ppPci != NULL && *ppPci != NULL; ppPci++) {
|
|
if ((*ppPci)->vendor == PCI_VENDOR_INTEL &&
|
|
(*ppPci)->func == 1) {
|
|
for (id = I810PciChipsets; id->PCIid != -1; id++) {
|
|
if (id->PCIid == (*ppPci)->chipType) {
|
|
/* Claim slot */
|
|
if (xf86CheckPciSlot((*ppPci)->bus, (*ppPci)->device,
|
|
(*ppPci)->func)) {
|
|
xf86ClaimPciSlot((*ppPci)->bus, (*ppPci)->device,
|
|
(*ppPci)->func, drv, id->PCIid,
|
|
NULL, FALSE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Look for Intel i8xx devices. */
|
|
numUsed = xf86MatchPciInstances(I810_NAME, PCI_VENDOR_INTEL,
|
|
I810Chipsets, I810PciChipsets,
|
|
devSections, numDevSections,
|
|
drv, &usedChips);
|
|
|
|
if (flags & PROBE_DETECT) {
|
|
if (numUsed > 0)
|
|
foundScreen = TRUE;
|
|
} else {
|
|
for (i = 0; i < numUsed; i++) {
|
|
ScrnInfoPtr pScrn = NULL;
|
|
|
|
/* Allocate new ScrnInfoRec and claim the slot */
|
|
if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
|
|
I810PciChipsets, NULL, NULL, NULL,
|
|
NULL, NULL))) {
|
|
EntityInfoPtr pEnt;
|
|
|
|
pEnt = xf86GetEntityInfo(usedChips[i]);
|
|
|
|
pScrn->driverVersion = I810_VERSION;
|
|
pScrn->driverName = I810_DRIVER_NAME;
|
|
pScrn->name = I810_NAME;
|
|
pScrn->Probe = I810Probe;
|
|
foundScreen = TRUE;
|
|
switch (pEnt->chipset) {
|
|
case PCI_CHIP_845_G:
|
|
case PCI_CHIP_I865_G:
|
|
I830InitpScrn(pScrn);
|
|
break;
|
|
case PCI_CHIP_I830_M:
|
|
case PCI_CHIP_I855_GM:
|
|
case PCI_CHIP_I915_G:
|
|
case PCI_CHIP_E7221_G:
|
|
case PCI_CHIP_I915_GM:
|
|
case PCI_CHIP_I945_G:
|
|
case PCI_CHIP_I945_GM:
|
|
case PCI_CHIP_I945_GME:
|
|
case PCI_CHIP_I965_G:
|
|
case PCI_CHIP_G35_G:
|
|
case PCI_CHIP_I965_Q:
|
|
case PCI_CHIP_I946_GZ:
|
|
case PCI_CHIP_I965_GM:
|
|
case PCI_CHIP_I965_GME:
|
|
case PCI_CHIP_G33_G:
|
|
case PCI_CHIP_Q35_G:
|
|
case PCI_CHIP_Q33_G:
|
|
case PCI_CHIP_IGD_GM:
|
|
xf86SetEntitySharable(usedChips[i]);
|
|
|
|
/* Allocate an entity private if necessary */
|
|
if (I830EntityIndex < 0)
|
|
I830EntityIndex = xf86AllocateEntityPrivateIndex();
|
|
|
|
pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
|
|
I830EntityIndex);
|
|
if (!pPriv->ptr) {
|
|
pPriv->ptr = xnfcalloc(sizeof(I830EntRec), 1);
|
|
pI830Ent = pPriv->ptr;
|
|
pI830Ent->lastInstance = -1;
|
|
} else {
|
|
pI830Ent = pPriv->ptr;
|
|
}
|
|
|
|
/*
|
|
* Set the entity instance for this instance of the driver.
|
|
* For dual head per card, instance 0 is the "master"
|
|
* instance, driving the primary head, and instance 1 is
|
|
* the "slave".
|
|
*/
|
|
pI830Ent->lastInstance++;
|
|
xf86SetEntityInstanceForScreen(pScrn,
|
|
pScrn->entityList[0], pI830Ent->lastInstance);
|
|
I830InitpScrn(pScrn);
|
|
break;
|
|
#ifndef I830_ONLY
|
|
default:
|
|
pScrn->PreInit = I810PreInit;
|
|
pScrn->ScreenInit = I810ScreenInit;
|
|
pScrn->SwitchMode = I810SwitchMode;
|
|
pScrn->AdjustFrame = I810AdjustFrame;
|
|
pScrn->EnterVT = I810EnterVT;
|
|
pScrn->LeaveVT = I810LeaveVT;
|
|
pScrn->FreeScreen = I810FreeScreen;
|
|
pScrn->ValidMode = I810ValidMode;
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
xfree(usedChips);
|
|
xfree(devSections);
|
|
|
|
return foundScreen;
|
|
}
|
|
#endif /* else XSERVER_LIBPCIACCESS */
|
|
|
|
#ifndef I830_ONLY
|
|
static void
|
|
I810ProbeDDC(ScrnInfoPtr pScrn, int index)
|
|
{
|
|
vbeInfoPtr pVbe;
|
|
|
|
if (xf86LoadSubModule(pScrn, "vbe")) {
|
|
pVbe = VBEInit(NULL, index);
|
|
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
|
|
vbeFree(pVbe);
|
|
}
|
|
}
|
|
|
|
static xf86MonPtr
|
|
I810DoDDC(ScrnInfoPtr pScrn, int index)
|
|
{
|
|
vbeInfoPtr pVbe;
|
|
xf86MonPtr MonInfo = NULL;
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
/* Honour Option "noDDC" */
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) {
|
|
return MonInfo;
|
|
}
|
|
|
|
if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
|
|
xf86LoaderReqSymLists(I810vbeSymbols, NULL);
|
|
MonInfo = vbeDoEDID(pVbe, NULL);
|
|
xf86PrintEDID(MonInfo);
|
|
xf86SetDDCproperties(pScrn, MonInfo);
|
|
vbeFree(pVbe);
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"this driver cannot do DDC without VBE\n");
|
|
}
|
|
|
|
return MonInfo;
|
|
}
|
|
|
|
/*
|
|
* I810PreInit --
|
|
*
|
|
* Do initial setup of the board before we know what resolution we will
|
|
* be running at.
|
|
*
|
|
*/
|
|
static Bool
|
|
I810PreInit(ScrnInfoPtr pScrn, int flags)
|
|
{
|
|
vgaHWPtr hwp;
|
|
I810Ptr pI810;
|
|
ClockRangePtr clockRanges;
|
|
int i;
|
|
MessageType from;
|
|
int flags24;
|
|
rgb defaultWeight = { 0, 0, 0 };
|
|
int mem;
|
|
Bool enable;
|
|
|
|
if (pScrn->numEntities != 1)
|
|
return FALSE;
|
|
|
|
/* Allocate driverPrivate */
|
|
if (!I810GetRec(pScrn))
|
|
return FALSE;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
|
|
pI810->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
|
|
if (pI810->pEnt->location.type != BUS_PCI)
|
|
return FALSE;
|
|
|
|
if (flags & PROBE_DETECT) {
|
|
I810ProbeDDC(pScrn, pI810->pEnt->index);
|
|
return TRUE;
|
|
}
|
|
|
|
/* The vgahw module should be loaded here when needed */
|
|
if (!xf86LoadSubModule(pScrn, "vgahw"))
|
|
return FALSE;
|
|
|
|
xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
|
|
|
|
/* Allocate a vgaHWRec */
|
|
if (!vgaHWGetHWRec(pScrn))
|
|
return FALSE;
|
|
hwp = VGAHWPTR(pScrn);
|
|
pI810->ioBase = hwp->PIOOffset;
|
|
|
|
pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
|
|
#if !XSERVER_LIBPCIACCESS
|
|
pI810->PciTag = pciTag(pI810->PciInfo->bus, pI810->PciInfo->device,
|
|
pI810->PciInfo->func);
|
|
#endif
|
|
|
|
if (xf86RegisterResources(pI810->pEnt->index, NULL, ResNone))
|
|
return FALSE;
|
|
pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
|
|
|
|
/* Set pScrn->monitor */
|
|
pScrn->monitor = pScrn->confScreen->monitor;
|
|
|
|
flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
|
|
if (!xf86SetDepthBpp(pScrn, 16, 0, 16, flags24)) {
|
|
return FALSE;
|
|
} else {
|
|
switch (pScrn->depth) {
|
|
case 8:
|
|
case 15:
|
|
case 16:
|
|
case 24:
|
|
break;
|
|
default:
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Given depth (%d) is not supported by i810 driver\n",
|
|
pScrn->depth);
|
|
return FALSE;
|
|
}
|
|
}
|
|
xf86PrintDepthBpp(pScrn);
|
|
|
|
switch (pScrn->bitsPerPixel) {
|
|
case 8:
|
|
case 16:
|
|
case 24:
|
|
break;
|
|
default:
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Given bpp (%d) is not supported by i810 driver\n",
|
|
pScrn->bitsPerPixel);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
|
|
return FALSE;
|
|
|
|
if (!xf86SetDefaultVisual(pScrn, -1))
|
|
return FALSE;
|
|
|
|
/* We use a programmable clock */
|
|
pScrn->progClock = TRUE;
|
|
|
|
pI810->cpp = pScrn->bitsPerPixel / 8;
|
|
|
|
/* Process the options */
|
|
xf86CollectOptions(pScrn, NULL);
|
|
if (!(pI810->Options = xalloc(sizeof(I810Options))))
|
|
return FALSE;
|
|
memcpy(pI810->Options, I810Options, sizeof(I810Options));
|
|
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options);
|
|
|
|
pScrn->rgbBits = 8;
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
|
|
pScrn->rgbBits = 6;
|
|
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE))
|
|
pI810->showCache = TRUE;
|
|
else
|
|
pI810->showCache = FALSE;
|
|
|
|
/* 6-BIT dac isn't reasonable for modes with > 8bpp */
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) &&
|
|
pScrn->bitsPerPixel > 8) {
|
|
OptionInfoPtr ptr;
|
|
|
|
ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT);
|
|
ptr->found = FALSE;
|
|
}
|
|
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
|
|
pI810->noAccel = TRUE;
|
|
|
|
if (!pI810->noAccel) {
|
|
if (!xf86LoadSubModule(pScrn, "xaa")) {
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(I810xaaSymbols, NULL);
|
|
}
|
|
|
|
#ifdef XF86DRI
|
|
pI810->directRenderingDisabled =
|
|
!xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
|
|
|
|
if (!pI810->directRenderingDisabled) {
|
|
if (pI810->noAccel) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
|
|
"needs 2D acceleration.\n");
|
|
pI810->directRenderingDisabled=TRUE;
|
|
} else if (pScrn->depth!=16) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
|
|
"runs only at 16-bit depth.\n");
|
|
pI810->directRenderingDisabled=TRUE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Get DDC info from monitor */
|
|
/* after xf86ProcessOptions,
|
|
* because it is controlled by options [no]vbe and [no]ddc
|
|
*/
|
|
pScrn->monitor->DDC = I810DoDDC(pScrn, pI810->pEnt->index);
|
|
|
|
/* We have to use PIO to probe, because we haven't mapped yet */
|
|
I810SetPIOAccess(pI810);
|
|
|
|
/*
|
|
* Set the Chipset and ChipRev, allowing config file entries to
|
|
* override.
|
|
*/
|
|
if (pI810->pEnt->device->chipset && *pI810->pEnt->device->chipset) {
|
|
pScrn->chipset = pI810->pEnt->device->chipset;
|
|
from = X_CONFIG;
|
|
} else if (pI810->pEnt->device->chipID >= 0) {
|
|
pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
|
|
pI810->pEnt->device->chipID);
|
|
from = X_CONFIG;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
|
|
pI810->pEnt->device->chipID);
|
|
} else {
|
|
from = X_PROBED;
|
|
pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
|
|
DEVICE_ID(pI810->PciInfo));
|
|
}
|
|
if (pI810->pEnt->device->chipRev >= 0) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
|
|
pI810->pEnt->device->chipRev);
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
|
|
(pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr;
|
|
#else
|
|
if (pI810->pEnt->device->MemBase != 0) {
|
|
pI810->LinearAddr = pI810->pEnt->device->MemBase;
|
|
from = X_CONFIG;
|
|
} else {
|
|
if (pI810->PciInfo->memBase[1] != 0) {
|
|
pI810->LinearAddr = pI810->PciInfo->memBase[0] & 0xFF000000;
|
|
from = X_PROBED;
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"No valid FB address in PCI config space\n");
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
|
|
(unsigned long)pI810->LinearAddr);
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr;
|
|
#else
|
|
if (pI810->pEnt->device->IOBase != 0) {
|
|
pI810->MMIOAddr = pI810->pEnt->device->IOBase;
|
|
from = X_CONFIG;
|
|
} else {
|
|
if (pI810->PciInfo->memBase[1]) {
|
|
pI810->MMIOAddr = pI810->PciInfo->memBase[1] & 0xFFF80000;
|
|
from = X_PROBED;
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"No valid MMIO address in PCI config space\n");
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
|
|
(unsigned long)pI810->MMIOAddr);
|
|
|
|
/* AGP GART support is required. Don't proceed any further if it isn't
|
|
* present.
|
|
*/
|
|
if (!xf86AgpGARTSupported()) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"AGP GART support is not available. Make sure your kernel has\n"
|
|
"\tagpgart support or that the agpgart kernel module is loaded.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find out memory bus frequency.
|
|
*/
|
|
{
|
|
uint32_t whtcfg_pamr_drp;
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP);
|
|
#else
|
|
whtcfg_pamr_drp = pciReadLong(pI810->PciTag, WHTCFG_PAMR_DRP);
|
|
#endif
|
|
|
|
/* Need this for choosing watermarks.
|
|
*/
|
|
if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133)
|
|
pI810->LmFreqSel = 133;
|
|
else
|
|
pI810->LmFreqSel = 100;
|
|
}
|
|
|
|
/* Default to 4MB framebuffer, which is sufficient for all
|
|
* supported 2d resolutions. If the user has specified a different
|
|
* size in the XF86Config, use that amount instead.
|
|
*
|
|
* Changed to 8 Meg so we can have acceleration by default (Mark).
|
|
*/
|
|
mem = I810CheckAvailableMemory(pScrn);
|
|
if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */
|
|
pScrn->videoRam = 8192;
|
|
else if (mem < 196608)
|
|
pScrn->videoRam = 16384; /* < 192 MB */
|
|
else
|
|
pScrn->videoRam = 24576;
|
|
|
|
from = X_DEFAULT;
|
|
|
|
if (pI810->pEnt->device->videoRam) {
|
|
pScrn->videoRam = pI810->pEnt->device->videoRam;
|
|
from = X_CONFIG;
|
|
}
|
|
|
|
if (mem > 0 && mem < pScrn->videoRam) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
|
|
" but the\n\t maximum AGP memory available is %dk.\n",
|
|
pScrn->videoRam, mem);
|
|
from = X_PROBED;
|
|
if (mem > (6 * 1024)) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Reducing video memory to 4MB\n");
|
|
pScrn->videoRam = 4096;
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
|
|
" is available. Cannot proceed.\n");
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, from,
|
|
"Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam);
|
|
|
|
/* Calculate Fixed Offsets depending on graphics aperture size */
|
|
{
|
|
#if XSERVER_LIBPCIACCESS
|
|
struct pci_device *bridge = intel_host_bridge ();
|
|
uint32_t smram_miscc;
|
|
|
|
pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC);
|
|
#else
|
|
PCITAG bridge;
|
|
long smram_miscc;
|
|
|
|
bridge = pciTag(0, 0, 0); /* This is always the host bridge */
|
|
smram_miscc = pciReadLong(bridge, SMRAM_MISCC);
|
|
#endif
|
|
|
|
if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
|
|
pI810->FbMapSize = 0x1000000;
|
|
pI810->DepthOffset = 0x1000000;
|
|
pI810->BackOffset = 0x1800000;
|
|
} else {
|
|
pI810->FbMapSize = 0x3000000;
|
|
pI810->DepthOffset = 0x3000000;
|
|
pI810->BackOffset = 0x3800000;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the driver can do gamma correction, it should call xf86SetGamma()
|
|
* here.
|
|
*/
|
|
{
|
|
Gamma zeros = { 0.0, 0.0, 0.0 };
|
|
|
|
if (!xf86SetGamma(pScrn, zeros)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pI810->MaxClock = 0;
|
|
if (pI810->pEnt->device->dacSpeeds[0]) {
|
|
switch (pScrn->bitsPerPixel) {
|
|
case 8:
|
|
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8];
|
|
break;
|
|
case 16:
|
|
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16];
|
|
break;
|
|
case 24:
|
|
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24];
|
|
break;
|
|
case 32: /* not supported */
|
|
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32];
|
|
break;
|
|
}
|
|
if (!pI810->MaxClock)
|
|
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0];
|
|
from = X_CONFIG;
|
|
} else {
|
|
switch (pScrn->bitsPerPixel) {
|
|
case 8:
|
|
pI810->MaxClock = 203000;
|
|
break;
|
|
case 16:
|
|
pI810->MaxClock = 163000;
|
|
break;
|
|
case 24:
|
|
pI810->MaxClock = 136000;
|
|
break;
|
|
case 32: /* not supported */
|
|
pI810->MaxClock = 86000;
|
|
}
|
|
}
|
|
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
|
|
clockRanges->next = NULL;
|
|
/* 9.4MHz appears to be the smallest that works. */
|
|
clockRanges->minClock = 9500;
|
|
clockRanges->maxClock = pI810->MaxClock;
|
|
clockRanges->clockIndex = -1;
|
|
clockRanges->interlaceAllowed = TRUE;
|
|
clockRanges->doubleScanAllowed = FALSE;
|
|
|
|
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
|
|
pScrn->display->modes, clockRanges,
|
|
#ifndef XF86DRI
|
|
0, 320, 1600, 64 * pScrn->bitsPerPixel,
|
|
#else
|
|
i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel,
|
|
#endif
|
|
200, 1200,
|
|
pScrn->display->virtualX, pScrn->display->virtualY,
|
|
pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
|
|
|
|
if (i == -1) {
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PruneDriverModes(pScrn);
|
|
|
|
if (!i || !pScrn->modes) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
|
|
|
|
pScrn->currentMode = pScrn->modes;
|
|
|
|
xf86PrintModes(pScrn);
|
|
|
|
xf86SetDpi(pScrn, 0, 0);
|
|
|
|
if (!xf86LoadSubModule(pScrn, "fb")) {
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(I810fbSymbols, NULL);
|
|
|
|
if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
|
|
if (!xf86LoadSubModule(pScrn, "ramdac")) {
|
|
I810FreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
|
|
}
|
|
|
|
if (xf86GetOptValInteger
|
|
(pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
|
|
"video overlay key set to 0x%x\n", pI810->colorKey);
|
|
} else {
|
|
pI810->colorKey = (1 << pScrn->offset.red) |
|
|
(1 << pScrn->offset.green) |
|
|
(((pScrn->mask.blue >> pScrn->offset.blue) -
|
|
1) << pScrn->offset.blue);
|
|
}
|
|
|
|
pI810->allowPageFlip=FALSE;
|
|
enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
|
|
|
|
#ifdef XF86DRI
|
|
if (!pI810->directRenderingDisabled) {
|
|
pI810->allowPageFlip = enable;
|
|
if (pI810->allowPageFlip == TRUE)
|
|
{
|
|
if (!xf86LoadSubModule(pScrn, "shadowfb")) {
|
|
pI810->allowPageFlip = 0;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Couldn't load shadowfb module:\n");
|
|
}
|
|
else {
|
|
xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
|
|
}
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
|
|
enable ? "enabled" : "disabled");
|
|
|
|
}
|
|
#endif
|
|
|
|
if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
|
|
&(pI810->numSurfaces))) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
|
|
pI810->numSurfaces);
|
|
if (pI810->numSurfaces > 7) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Using 7 XvMC Surfaces (Maximum Allowed).\n");
|
|
pI810->numSurfaces = 7;
|
|
}
|
|
if (pI810->numSurfaces < 6) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Using 6 XvMC Surfaces (Minimum Allowed).\n");
|
|
pI810->numSurfaces = 6;
|
|
}
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
|
|
pI810->numSurfaces = 0;
|
|
}
|
|
|
|
#ifdef XF86DRI
|
|
/* Load the dri module if requested. */
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
|
|
if (xf86LoadSubModule(pScrn, "dri")) {
|
|
xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* We won't be using the VGA access after the probe */
|
|
I810SetMMIOAccess(pI810);
|
|
xf86SetOperatingState(resVgaIo, pI810->pEnt->index, ResUnusedOpr);
|
|
xf86SetOperatingState(resVgaMem, pI810->pEnt->index, ResDisableOpr);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
I810MapMMIO(ScrnInfoPtr pScrn)
|
|
{
|
|
int mmioFlags;
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
#if XSERVER_LIBPCIACCESS
|
|
struct pci_device *const device = pI810->PciInfo;
|
|
int err;
|
|
#endif
|
|
|
|
#if !defined(__alpha__)
|
|
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
|
|
#else
|
|
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
|
|
#endif
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
err = pci_device_map_range (device,
|
|
pI810->MMIOAddr,
|
|
I810_REG_SIZE,
|
|
PCI_DEV_MAP_FLAG_WRITABLE,
|
|
(void **) &pI810->MMIOBase);
|
|
if (err)
|
|
{
|
|
xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
|
|
"Unable to map mmio BAR. %s (%d)\n",
|
|
strerror (err), err);
|
|
return FALSE;
|
|
}
|
|
#else
|
|
pI810->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
|
|
pI810->PciTag,
|
|
pI810->MMIOAddr, I810_REG_SIZE);
|
|
if (!pI810->MMIOBase)
|
|
return FALSE;
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
I810MapMem(ScrnInfoPtr pScrn)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
#if XSERVER_LIBPCIACCESS
|
|
struct pci_device *const device = pI810->PciInfo;
|
|
int err;
|
|
#else
|
|
long i;
|
|
#endif
|
|
|
|
if (!I810MapMMIO(pScrn))
|
|
return FALSE;
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
err = pci_device_map_range (device,
|
|
pI810->LinearAddr,
|
|
pI810->FbMapSize,
|
|
PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
|
|
(void **) &pI810->FbBase);
|
|
if (err)
|
|
{
|
|
xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
|
|
"Unable to map frame buffer BAR. %s (%d)\n",
|
|
strerror (err), err);
|
|
return FALSE;
|
|
}
|
|
#else
|
|
for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
|
|
|
|
pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
|
|
pI810->PciTag,
|
|
pI810->LinearAddr, i);
|
|
if (!pI810->FbBase)
|
|
return FALSE;
|
|
#endif
|
|
|
|
pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
I810UnmapMMIO(ScrnInfoPtr pScrn)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE);
|
|
#else
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
|
|
I810_REG_SIZE);
|
|
#endif
|
|
pI810->MMIOBase = NULL;
|
|
}
|
|
|
|
static Bool
|
|
I810UnmapMem(ScrnInfoPtr pScrn)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
#if XSERVER_LIBPCIACCESS
|
|
pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize);
|
|
#else
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
|
|
pI810->FbMapSize);
|
|
#endif
|
|
pI810->FbBase = NULL;
|
|
I810UnmapMMIO(pScrn);
|
|
return TRUE;
|
|
}
|
|
|
|
/* Famous last words
|
|
*/
|
|
void
|
|
I810PrintErrorState(ScrnInfoPtr pScrn)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
|
|
(unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR));
|
|
|
|
ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR),
|
|
(unsigned long) INREG(IPEHR));
|
|
|
|
ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
|
|
(unsigned long) INREG(LP_RING + RING_TAIL),
|
|
(unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
|
|
(unsigned long) INREG(LP_RING + RING_LEN),
|
|
(unsigned long) INREG(LP_RING + RING_START));
|
|
|
|
ErrorF("eir: %x esr: %x emr: %x\n",
|
|
INREG16(EIR), INREG16(ESR), INREG16(EMR));
|
|
|
|
ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
|
|
|
|
ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE),
|
|
(unsigned long) INREG(INST_PS));
|
|
|
|
ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
|
|
INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
|
|
}
|
|
|
|
/*
|
|
* I810Save --
|
|
*
|
|
* This function saves the video state. It reads all of the SVGA registers
|
|
* into the vgaI810Rec data structure. There is in general no need to
|
|
* mask out bits here - just read the registers.
|
|
*/
|
|
static void
|
|
DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
|
|
Bool saveFonts)
|
|
{
|
|
I810Ptr pI810;
|
|
vgaHWPtr hwp;
|
|
int i;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
/*
|
|
* This function will handle creating the data structure and filling
|
|
* in the generic VGA portion.
|
|
*/
|
|
if (saveFonts)
|
|
vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP);
|
|
else
|
|
vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
|
|
|
|
/*
|
|
* The port I/O code necessary to read in the extended registers
|
|
* into the fields of the vgaI810Rec structure goes here.
|
|
*/
|
|
i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL);
|
|
i810Reg->AddressMapping = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
|
|
i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
|
|
i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
|
|
i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
|
|
i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
|
|
|
|
i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL);
|
|
i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
|
|
i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
|
|
i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
|
|
i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
|
|
i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
|
|
i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET);
|
|
i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL);
|
|
|
|
i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
|
|
i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
|
|
i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
|
|
i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
|
|
i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
i810Reg->Fence[i] = INREG(FENCE + i * 4);
|
|
|
|
i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
|
|
i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
|
|
i810Reg->LprbStart = INREG(LP_RING + RING_START);
|
|
i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
|
|
|
|
if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
|
|
i810Reg->LprbLen & RING_VALID) {
|
|
I810PrintErrorState(pScrn);
|
|
FatalError("Active ring not flushed\n");
|
|
}
|
|
}
|
|
|
|
static void
|
|
I810Save(ScrnInfoPtr pScrn)
|
|
{
|
|
vgaHWPtr hwp;
|
|
I810Ptr pI810;
|
|
uint32_t temp;
|
|
|
|
hwp = VGAHWPTR(pScrn);
|
|
pI810 = I810PTR(pScrn);
|
|
DoSave(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
|
|
|
|
temp = INREG(MEMMODE);
|
|
temp |= 4;
|
|
OUTREG(MEMMODE, temp);
|
|
}
|
|
|
|
static void
|
|
i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode)
|
|
{
|
|
int i;
|
|
|
|
ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg);
|
|
|
|
ErrorF("SEQ: ");
|
|
for (i = 0; i < vgaReg->numSequencer; i++) {
|
|
if ((i & 7) == 0)
|
|
ErrorF("\n");
|
|
ErrorF(" %d: %x", i, vgaReg->Sequencer[i]);
|
|
}
|
|
ErrorF("\n");
|
|
|
|
ErrorF("CRTC: ");
|
|
for (i = 0; i < vgaReg->numCRTC; i++) {
|
|
if ((i & 3) == 0)
|
|
ErrorF("\n");
|
|
ErrorF(" %d: %x", i, vgaReg->CRTC[i]);
|
|
}
|
|
ErrorF("\n");
|
|
|
|
ErrorF("GFX: ");
|
|
for (i = 0; i < vgaReg->numGraphics; i++) {
|
|
if ((i & 7) == 0)
|
|
ErrorF("\n");
|
|
ErrorF(" %d: %x", i, vgaReg->Graphics[i]);
|
|
}
|
|
ErrorF("\n");
|
|
|
|
ErrorF("ATTR: ");
|
|
for (i = 0; i < vgaReg->numAttribute; i++) {
|
|
if ((i & 7) == 0)
|
|
ErrorF("\n");
|
|
ErrorF(" %d: %x", i, vgaReg->Attribute[i]);
|
|
}
|
|
ErrorF("\n");
|
|
|
|
ErrorF(" DisplayControl: %x\n", mode->DisplayControl);
|
|
ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
|
|
ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
|
|
ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
|
|
ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M);
|
|
ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N);
|
|
ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
|
|
ErrorF(" AddressMapping: %x\n", mode->AddressMapping);
|
|
ErrorF(" IOControl: %x\n", mode->IOControl);
|
|
ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl);
|
|
ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal);
|
|
ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
|
|
ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
|
|
ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
|
|
ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal);
|
|
ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank);
|
|
ErrorF(" ExtOffset: %x\n", mode->ExtOffset);
|
|
ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl);
|
|
ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
|
|
ErrorF(" LprbTail: %x\n", mode->LprbTail);
|
|
ErrorF(" LprbHead: %x\n", mode->LprbHead);
|
|
ErrorF(" LprbStart: %x\n", mode->LprbStart);
|
|
ErrorF(" LprbLen: %x\n", mode->LprbLen);
|
|
}
|
|
|
|
static void
|
|
DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
|
|
Bool restoreFonts)
|
|
{
|
|
I810Ptr pI810;
|
|
vgaHWPtr hwp;
|
|
unsigned char temp;
|
|
unsigned int itemp;
|
|
int i;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
|
|
ErrorF("Setting mode in I810Restore:\n");
|
|
i810PrintMode(vgaReg, i810Reg);
|
|
}
|
|
|
|
vgaHWProtect(pScrn, TRUE);
|
|
|
|
usleep(50000);
|
|
|
|
/* Turn off DRAM Refresh */
|
|
temp = INREG8(DRAM_ROW_CNTL_HI);
|
|
temp &= ~DRAM_REFRESH_RATE;
|
|
temp |= DRAM_REFRESH_DISABLE;
|
|
OUTREG8(DRAM_ROW_CNTL_HI, temp);
|
|
|
|
usleep(1000); /* Wait 1 ms */
|
|
|
|
/* Write the M, N and P values */
|
|
OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M);
|
|
OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N);
|
|
OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
|
|
|
|
/*
|
|
* Turn on 8 bit dac mode, if requested. This is needed to make
|
|
* sure that vgaHWRestore writes the values into the DAC properly.
|
|
* The problem occurs if 8 bit dac mode is requested and the HW is
|
|
* in 6 bit dac mode. If this happens, all the values are
|
|
* automatically shifted left twice by the HW and incorrect colors
|
|
* will be displayed on the screen. The only time this can happen
|
|
* is at server startup time and when switching back from a VT.
|
|
*/
|
|
temp = INREG8(PIXPIPE_CONFIG_0);
|
|
temp &= 0x7F; /* Save all but the 8 bit dac mode bit */
|
|
temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
|
|
OUTREG8(PIXPIPE_CONFIG_0, temp);
|
|
|
|
/*
|
|
* Code to restore any SVGA registers that have been saved/modified
|
|
* goes here. Note that it is allowable, and often correct, to
|
|
* only modify certain bits in a register by a read/modify/write cycle.
|
|
*
|
|
* A special case - when using an external clock-setting program,
|
|
* this function must not change bits associated with the clock
|
|
* selection. This condition can be checked by the condition:
|
|
*
|
|
* if (i810Reg->std.NoClock >= 0)
|
|
* restore clock-select bits.
|
|
*/
|
|
if (restoreFonts)
|
|
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
|
|
else
|
|
vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
|
|
|
|
hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
|
|
hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
|
|
hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
|
|
hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
|
|
hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
|
|
hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
|
|
hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);
|
|
|
|
temp = hwp->readCrtc(hwp, INTERLACE_CNTL);
|
|
temp &= ~INTERLACE_ENABLE;
|
|
temp |= i810Reg->InterlaceControl;
|
|
hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
|
|
|
|
temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
|
|
temp &= 0xE0; /* Save reserved bits 7:5 */
|
|
temp |= i810Reg->AddressMapping;
|
|
pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp);
|
|
|
|
/* Setting the OVRACT Register for video overlay */
|
|
{
|
|
uint32_t LCD_TV_Control = INREG(LCD_TV_C);
|
|
uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL);
|
|
uint32_t ActiveStart, ActiveEnd;
|
|
|
|
if((LCD_TV_Control & LCD_TV_ENABLE)
|
|
&& !(LCD_TV_Control & LCD_TV_VGAMOD)
|
|
&& TV_HTotal) {
|
|
ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
|
|
ActiveEnd = (TV_HTotal & 0x3ff) - 31;
|
|
} else {
|
|
ActiveStart = i810Reg->OverlayActiveStart;
|
|
ActiveEnd = i810Reg->OverlayActiveEnd;
|
|
}
|
|
OUTREG(LCD_TV_OVRACT,
|
|
(ActiveEnd << 16) | ActiveStart);
|
|
}
|
|
|
|
/* Turn on DRAM Refresh */
|
|
temp = INREG8(DRAM_ROW_CNTL_HI);
|
|
temp &= ~DRAM_REFRESH_RATE;
|
|
temp |= DRAM_REFRESH_60HZ;
|
|
OUTREG8(DRAM_ROW_CNTL_HI, temp);
|
|
|
|
temp = INREG8(BITBLT_CNTL);
|
|
temp &= ~COLEXP_MODE;
|
|
temp |= i810Reg->BitBLTControl;
|
|
OUTREG8(BITBLT_CNTL, temp);
|
|
|
|
temp = INREG8(DISPLAY_CNTL);
|
|
temp &= ~(VGA_WRAP_MODE | GUI_MODE);
|
|
temp |= i810Reg->DisplayControl;
|
|
OUTREG8(DISPLAY_CNTL, temp);
|
|
|
|
temp = INREG8(PIXPIPE_CONFIG_0);
|
|
temp &= 0x64; /* Save reserved bits 6:5,2 */
|
|
temp |= i810Reg->PixelPipeCfg0;
|
|
OUTREG8(PIXPIPE_CONFIG_0, temp);
|
|
|
|
temp = INREG8(PIXPIPE_CONFIG_2);
|
|
temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
|
|
temp |= i810Reg->PixelPipeCfg2;
|
|
OUTREG8(PIXPIPE_CONFIG_2, temp);
|
|
|
|
temp = INREG8(PIXPIPE_CONFIG_1);
|
|
temp &= ~DISPLAY_COLOR_MODE;
|
|
temp &= 0xEF; /* Restore the CRT control bit */
|
|
temp |= i810Reg->PixelPipeCfg1;
|
|
OUTREG8(PIXPIPE_CONFIG_1, temp);
|
|
|
|
OUTREG16(EIR, 0);
|
|
|
|
itemp = INREG(FWATER_BLC);
|
|
itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
|
|
MM_BURST_LENGTH | MM_FIFO_WATERMARK);
|
|
itemp |= i810Reg->LMI_FIFO_Watermark;
|
|
OUTREG(FWATER_BLC, itemp);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
|
|
if (I810_DEBUG & DEBUG_VERBOSE_VGA)
|
|
ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
|
|
}
|
|
|
|
/* First disable the ring buffer (Need to wait for empty first?, if so
|
|
* should probably do it before entering this section)
|
|
*/
|
|
itemp = INREG(LP_RING + RING_LEN);
|
|
itemp &= ~RING_VALID_MASK;
|
|
OUTREG(LP_RING + RING_LEN, itemp);
|
|
|
|
/* Set up the low priority ring buffer.
|
|
*/
|
|
OUTREG(LP_RING + RING_TAIL, 0);
|
|
OUTREG(LP_RING + RING_HEAD, 0);
|
|
|
|
pI810->LpRing->head = 0;
|
|
pI810->LpRing->tail = 0;
|
|
|
|
itemp = INREG(LP_RING + RING_START);
|
|
itemp &= ~(START_ADDR);
|
|
itemp |= i810Reg->LprbStart;
|
|
OUTREG(LP_RING + RING_START, itemp);
|
|
|
|
itemp = INREG(LP_RING + RING_LEN);
|
|
itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
|
|
itemp |= i810Reg->LprbLen;
|
|
OUTREG(LP_RING + RING_LEN, itemp);
|
|
|
|
if (!(vgaReg->Attribute[0x10] & 0x1)) {
|
|
usleep(50000);
|
|
if (restoreFonts)
|
|
vgaHWRestore(pScrn, vgaReg,
|
|
VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
|
|
else
|
|
vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
|
|
}
|
|
|
|
vgaHWProtect(pScrn, FALSE);
|
|
|
|
temp = hwp->readCrtc(hwp, IO_CTNL);
|
|
temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
|
|
temp |= i810Reg->IOControl;
|
|
hwp->writeCrtc(hwp, IO_CTNL, temp);
|
|
}
|
|
|
|
static void
|
|
I810SetRingRegs(ScrnInfoPtr pScrn)
|
|
{
|
|
unsigned int itemp;
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
OUTREG(LP_RING + RING_TAIL, 0);
|
|
OUTREG(LP_RING + RING_HEAD, 0);
|
|
|
|
itemp = INREG(LP_RING + RING_START);
|
|
itemp &= ~(START_ADDR);
|
|
itemp |= pI810->LpRing->mem.Start;
|
|
OUTREG(LP_RING + RING_START, itemp);
|
|
|
|
itemp = INREG(LP_RING + RING_LEN);
|
|
itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
|
|
itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
|
|
OUTREG(LP_RING + RING_LEN, itemp);
|
|
}
|
|
|
|
static void
|
|
I810Restore(ScrnInfoPtr pScrn)
|
|
{
|
|
vgaHWPtr hwp;
|
|
I810Ptr pI810;
|
|
|
|
hwp = VGAHWPTR(pScrn);
|
|
pI810 = I810PTR(pScrn);
|
|
|
|
DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
|
|
}
|
|
|
|
/*
|
|
* I810CalcVCLK --
|
|
*
|
|
* Determine the closest clock frequency to the one requested.
|
|
*/
|
|
|
|
#define MAX_VCO_FREQ 600.0
|
|
#define TARGET_MAX_N 30
|
|
#define REF_FREQ 24.0
|
|
|
|
#define CALC_VCLK(m,n,p) \
|
|
(double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
|
|
|
|
static void
|
|
I810CalcVCLK(ScrnInfoPtr pScrn, double freq)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
I810RegPtr i810Reg = &pI810->ModeReg;
|
|
int m, n, p;
|
|
double f_out, f_best;
|
|
double f_err;
|
|
double f_vco;
|
|
int m_best = 0, n_best = 0, p_best = 0;
|
|
double f_target = freq;
|
|
double err_max = 0.005;
|
|
double err_target = 0.001;
|
|
double err_best = 999999.0;
|
|
|
|
p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);
|
|
/* Make sure p is within range. */
|
|
if (p_best > 5) {
|
|
p_best = p = 5;
|
|
}
|
|
|
|
f_vco = f_target * (1 << p);
|
|
|
|
n = 2;
|
|
do {
|
|
n++;
|
|
m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
|
|
if (m < 3)
|
|
m = 3;
|
|
f_out = CALC_VCLK(m, n, p);
|
|
f_err = 1.0 - (f_target / f_out);
|
|
if (fabs(f_err) < err_max) {
|
|
m_best = m;
|
|
n_best = n;
|
|
f_best = f_out;
|
|
err_best = f_err;
|
|
}
|
|
} while ((fabs(f_err) >= err_target) &&
|
|
((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
|
|
|
|
if (fabs(f_err) < err_target) {
|
|
m_best = m;
|
|
n_best = n;
|
|
}
|
|
|
|
i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;
|
|
i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;
|
|
i810Reg->VideoClk2_DivisorSel = (p_best << 4);
|
|
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
|
|
"Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
|
|
"[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
|
|
i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
|
|
i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
|
|
}
|
|
|
|
static Bool
|
|
I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
I810RegPtr i810Reg = &pI810->ModeReg;
|
|
vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
|
|
double dclk = mode->Clock / 1000.0;
|
|
|
|
switch (pScrn->bitsPerPixel) {
|
|
case 8:
|
|
pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
|
|
i810Reg->ExtOffset = pScrn->displayWidth >> 11;
|
|
i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
|
|
i810Reg->BitBLTControl = COLEXP_8BPP;
|
|
break;
|
|
case 16:
|
|
if (pScrn->weight.green == 5) {
|
|
i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
|
|
} else {
|
|
i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
|
|
}
|
|
pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
|
|
i810Reg->ExtOffset = pScrn->displayWidth >> 10;
|
|
i810Reg->BitBLTControl = COLEXP_16BPP;
|
|
|
|
/* Enable Palette Programming for Direct Color visuals. -jens */
|
|
i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
|
|
break;
|
|
case 24:
|
|
pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
|
|
i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
|
|
|
|
i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
|
|
i810Reg->BitBLTControl = COLEXP_24BPP;
|
|
|
|
/* Enable Palette Programming for Direct Color visuals. -jens */
|
|
i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Turn on 8 bit dac if requested */
|
|
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
|
|
i810Reg->PixelPipeCfg0 = DAC_6_BIT;
|
|
else
|
|
i810Reg->PixelPipeCfg0 = DAC_8_BIT;
|
|
|
|
/* Do not delay CRT Blank: needed for video overlay */
|
|
i810Reg->PixelPipeCfg1 |= 0x10;
|
|
|
|
/* Turn on Extended VGA Interpretation */
|
|
i810Reg->IOControl = EXTENDED_CRTC_CNTL;
|
|
|
|
/* Turn on linear and page mapping */
|
|
i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
|
|
|
|
/* Turn on GUI mode */
|
|
i810Reg->DisplayControl = HIRES_MODE;
|
|
|
|
/* Calculate the extended CRTC regs */
|
|
i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
|
|
i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
|
|
i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
|
|
i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
|
|
i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
|
|
i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
|
|
|
|
/*
|
|
* the KGA fix in vgaHW.c results in the first
|
|
* scanline and the first character clock (8 pixels)
|
|
* of each scanline thereafter on display with an i810
|
|
* to be blank. Restoring CRTC 3, 5, & 22 to their
|
|
* "theoretical" values corrects the problem. KAO.
|
|
*/
|
|
pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
|
|
pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
|
|
| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
|
|
pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
|
|
|
|
i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
|
|
vgaHWVBlankKGA(mode, pVga, 8, 0);
|
|
|
|
/*
|
|
* The following workarounds are needed to get video overlay working
|
|
* at 1024x768 and 1280x1024 display resolutions.
|
|
*/
|
|
if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
|
|
i810Reg->ExtVertBlankStart = 2;
|
|
}
|
|
if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
|
|
i810Reg->ExtVertBlankStart = 3;
|
|
}
|
|
|
|
/* OVRACT Register */
|
|
i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
|
|
i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
|
|
|
|
/* Turn on interlaced mode if necessary */
|
|
if (mode->Flags & V_INTERLACE) {
|
|
i810Reg->InterlaceControl = INTERLACE_ENABLE;
|
|
i810Reg->ExtVertDispEnd *= 2;
|
|
} else
|
|
i810Reg->InterlaceControl = INTERLACE_DISABLE;
|
|
|
|
/*
|
|
* Set the overscan color to 0.
|
|
* NOTE: This only affects >8bpp mode.
|
|
*/
|
|
pVga->Attribute[0x11] = 0;
|
|
|
|
/*
|
|
* Calculate the VCLK that most closely matches the requested dot
|
|
* clock.
|
|
*/
|
|
I810CalcVCLK(pScrn, dclk);
|
|
|
|
/* Since we program the clocks ourselves, always use VCLK2. */
|
|
pVga->MiscOutReg |= 0x0C;
|
|
|
|
/* Calculate the FIFO Watermark and Burst Length. */
|
|
i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);
|
|
|
|
/* Setup the ring buffer */
|
|
i810Reg->LprbTail = 0;
|
|
i810Reg->LprbHead = 0;
|
|
i810Reg->LprbStart = pI810->LpRing->mem.Start;
|
|
|
|
if (i810Reg->LprbStart)
|
|
i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |
|
|
RING_NO_REPORT | RING_VALID);
|
|
else
|
|
i810Reg->LprbLen = RING_INVALID;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
vgaHWPtr hwp;
|
|
I810Ptr pI810;
|
|
|
|
hwp = VGAHWPTR(pScrn);
|
|
pI810 = I810PTR(pScrn);
|
|
|
|
vgaHWUnlock(hwp);
|
|
|
|
if (!vgaHWInit(pScrn, mode))
|
|
return FALSE;
|
|
|
|
pScrn->vtSema = TRUE;
|
|
|
|
if (!I810SetMode(pScrn, mode))
|
|
return FALSE;
|
|
|
|
#ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
|
|
pI810->LockHeld = 1;
|
|
}
|
|
#endif
|
|
|
|
DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
|
|
|
|
#ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
|
|
pI810->LockHeld = 0;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,
|
|
LOCO * colors, VisualPtr pVisual)
|
|
{
|
|
I810Ptr pI810;
|
|
vgaHWPtr hwp;
|
|
int i, j, index;
|
|
unsigned char r, g, b;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
index = indices[i];
|
|
r = colors[index].red;
|
|
g = colors[index].green;
|
|
b = colors[index].blue;
|
|
for (j = 0; j < 8; j++) {
|
|
hwp->writeDacWriteAddr(hwp, (index << 3) + j);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
I810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,
|
|
LOCO * colors, VisualPtr pVisual)
|
|
{
|
|
I810Ptr pI810;
|
|
vgaHWPtr hwp;
|
|
int i, index;
|
|
unsigned char r, g, b;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
/* Load all four entries in each of the 64 color ranges. -jens */
|
|
for (i = 0; i < numColors; i++) {
|
|
index = indices[i / 2];
|
|
r = colors[index].red;
|
|
b = colors[index].blue;
|
|
index = indices[i];
|
|
g = colors[index].green;
|
|
|
|
hwp->writeDacWriteAddr(hwp, index << 2);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
i++;
|
|
index = indices[i];
|
|
g = colors[index].green;
|
|
|
|
hwp->writeDacWriteAddr(hwp, index << 2);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
|
|
hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
}
|
|
}
|
|
|
|
static void
|
|
I810LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices,
|
|
LOCO * colors, VisualPtr pVisual)
|
|
{
|
|
I810Ptr pI810;
|
|
vgaHWPtr hwp;
|
|
int i, index;
|
|
unsigned char r, g, b;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
index = indices[i];
|
|
r = colors[index].red;
|
|
g = colors[index].green;
|
|
b = colors[index].blue;
|
|
hwp->writeDacWriteAddr(hwp, index);
|
|
hwp->writeDacData(hwp, r);
|
|
hwp->writeDacData(hwp, g);
|
|
hwp->writeDacData(hwp, b);
|
|
}
|
|
}
|
|
|
|
Bool
|
|
I810AllocateFront(ScrnInfoPtr pScrn)
|
|
{
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
int cache_lines = -1;
|
|
|
|
if (pI810->DoneFrontAlloc)
|
|
return TRUE;
|
|
|
|
memset(&(pI810->FbMemBox), 0, sizeof(BoxRec));
|
|
/* Alloc FrontBuffer/Ring/Accel memory */
|
|
pI810->FbMemBox.x1 = 0;
|
|
pI810->FbMemBox.x2 = pScrn->displayWidth;
|
|
pI810->FbMemBox.y1 = 0;
|
|
pI810->FbMemBox.y2 = pScrn->virtualY;
|
|
|
|
xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines);
|
|
|
|
if (cache_lines < 0) {
|
|
/* make sure there is enough for two DVD sized YUV buffers */
|
|
cache_lines = (pScrn->depth == 24) ? 256 : 384;
|
|
if (pScrn->displayWidth <= 1024)
|
|
cache_lines *= 2;
|
|
}
|
|
/* Make sure there's enough space for cache_lines.
|
|
*
|
|
* Had a bug here where maxCacheLines was computed to be less than 0.
|
|
* Not sure why 256 was initially subtracted from videoRam in the
|
|
* maxCacheLines calculation, but that was causing a problem
|
|
* for configurations that have exactly enough Ram for the framebuffer.
|
|
* Common code should catch the case where there isn't enough space for
|
|
* framebuffer, we'll just check for no space for cache_lines. -jens
|
|
*
|
|
*/
|
|
{
|
|
int maxCacheLines;
|
|
|
|
maxCacheLines = (pScrn->videoRam * 1024 /
|
|
(pScrn->bitsPerPixel / 8) /
|
|
pScrn->displayWidth) - pScrn->virtualY;
|
|
if (maxCacheLines < 0)
|
|
maxCacheLines = 0;
|
|
if (cache_lines > maxCacheLines)
|
|
cache_lines = maxCacheLines;
|
|
}
|
|
pI810->FbMemBox.y2 += cache_lines;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Adding %i scanlines for pixmap caching\n", cache_lines);
|
|
|
|
/* Reserve room for the framebuffer and pixcache. Put at the top
|
|
* of memory so we can have nice alignment for the tiled regions at
|
|
* the start of memory.
|
|
*/
|
|
|
|
if (!I810AllocLow(&(pI810->FrontBuffer),
|
|
&(pI810->SysMem),
|
|
((pI810->FbMemBox.x2 *
|
|
pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095)) {
|
|
xf86DrvMsg(pScrn->scrnIndex,
|
|
X_WARNING, "Framebuffer allocation failed\n");
|
|
return FALSE;
|
|
} else
|
|
DPRINTF(PFX,
|
|
"Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
|
|
pI810->FrontBuffer.Start,
|
|
pI810->FrontBuffer.Size / 1024, pI810->FrontBuffer.Size);
|
|
|
|
memset(pI810->LpRing, 0, sizeof(I810RingBuffer));
|
|
if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) {
|
|
DPRINTF(PFX,
|
|
"Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
|
|
pI810->LpRing->mem.Start,
|
|
pI810->LpRing->mem.Size / 1024, pI810->LpRing->mem.Size);
|
|
|
|
pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1;
|
|
pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
|
|
pI810->LpRing->head = 0;
|
|
pI810->LpRing->tail = 0;
|
|
pI810->LpRing->space = 0;
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Ring buffer allocation failed\n");
|
|
return (FALSE);
|
|
}
|
|
|
|
if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) ||
|
|
I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) {
|
|
DPRINTF(PFX,
|
|
"Scratch memory at 0x%.8x (%luk, %lu bytes)\n",
|
|
pI810->Scratch.Start,
|
|
pI810->Scratch.Size / 1024, pI810->Scratch.Size);
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n");
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Scratch memory allocation failed\n");
|
|
return (FALSE);
|
|
}
|
|
|
|
pI810->DoneFrontAlloc = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
|
|
{
|
|
ScrnInfoPtr pScrn;
|
|
vgaHWPtr hwp;
|
|
I810Ptr pI810;
|
|
VisualPtr visual;
|
|
MessageType driFrom = X_DEFAULT;
|
|
|
|
pScrn = xf86Screens[pScreen->myNum];
|
|
pI810 = I810PTR(pScrn);
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
pI810->LpRing = xcalloc(sizeof(I810RingBuffer),1);
|
|
if (!pI810->LpRing) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Could not allocate lpring data structure.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
miClearVisualTypes();
|
|
|
|
/* Re-implemented Direct Color support, -jens */
|
|
if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
|
|
pScrn->rgbBits, pScrn->defaultVisual))
|
|
return FALSE;
|
|
|
|
if (!miSetPixmapDepths())
|
|
return FALSE;
|
|
|
|
{
|
|
I810RegPtr i810Reg = &pI810->ModeReg;
|
|
int i;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
i810Reg->Fence[i] = 0;
|
|
}
|
|
|
|
/* Have to init the DRM earlier than in other drivers to get agp
|
|
* memory. Wonder if this is going to be a problem...
|
|
*/
|
|
|
|
#ifdef XF86DRI
|
|
/*
|
|
* Setup DRI after visuals have been established, but before fbScreenInit
|
|
* is called. fbScreenInit will eventually call into the drivers
|
|
* InitGLXVisuals call back.
|
|
*/
|
|
/*
|
|
* pI810->directRenderingDisabled is set once in PreInit. Reinitialise
|
|
* pI810->directRenderingEnabled based on it each generation.
|
|
*/
|
|
pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
|
|
|
|
if (pI810->directRenderingEnabled==TRUE)
|
|
pI810->directRenderingEnabled = I810DRIScreenInit(pScreen);
|
|
else
|
|
driFrom = X_CONFIG;
|
|
|
|
#else
|
|
pI810->directRenderingEnabled = FALSE;
|
|
if (!I810AllocateGARTMemory(pScrn))
|
|
return FALSE;
|
|
if (!I810AllocateFront(pScrn))
|
|
return FALSE;
|
|
#endif
|
|
|
|
if (!I810MapMem(pScrn))
|
|
return FALSE;
|
|
|
|
pScrn->memPhysBase = (unsigned long)pI810->LinearAddr;
|
|
pScrn->fbOffset = 0;
|
|
|
|
vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0);
|
|
vgaHWGetIOBase(hwp);
|
|
if (!vgaHWMapMem(pScrn))
|
|
return FALSE;
|
|
|
|
I810Save(pScrn);
|
|
if (!I810ModeInit(pScrn, pScrn->currentMode))
|
|
return FALSE;
|
|
|
|
I810SaveScreen(pScreen, FALSE);
|
|
I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
|
|
|
|
if (!fbScreenInit(pScreen, pI810->FbBase + pScrn->fbOffset,
|
|
pScrn->virtualX, pScrn->virtualY,
|
|
pScrn->xDpi, pScrn->yDpi,
|
|
pScrn->displayWidth, pScrn->bitsPerPixel))
|
|
return FALSE;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
fbPictureInit(pScreen, NULL, 0);
|
|
|
|
xf86SetBlackWhitePixels(pScreen);
|
|
|
|
#ifdef XF86DRI
|
|
if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) {
|
|
pI810->directRenderingEnabled = FALSE;
|
|
driFrom = X_PROBED;
|
|
I810DRICloseScreen(pScreen);
|
|
}
|
|
|
|
if (!pI810->directRenderingEnabled) {
|
|
pI810->DoneFrontAlloc = FALSE;
|
|
if (!I810AllocateGARTMemory(pScrn))
|
|
return FALSE;
|
|
if (!I810AllocateFront(pScrn))
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
I810DGAInit(pScreen);
|
|
|
|
if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Failed to init memory manager\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) {
|
|
if (pI810->LpRing->mem.Size != 0) {
|
|
I810SetRingRegs(pScrn);
|
|
|
|
if (!I810AccelInit(pScreen)) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Hardware acceleration initialization failed\n");
|
|
} else /* PK added 16.02.2004 */
|
|
I810EmitFlush(pScrn);
|
|
}
|
|
}
|
|
|
|
miInitializeBackingStore(pScreen);
|
|
xf86SetBackingStore(pScreen);
|
|
xf86SetSilkenMouse(pScreen);
|
|
|
|
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
|
|
|
|
if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
|
|
if (!I810CursorInit(pScreen)) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Hardware cursor initialization failed\n");
|
|
}
|
|
}
|
|
|
|
if (!miCreateDefColormap(pScreen))
|
|
return FALSE;
|
|
|
|
/* Use driver specific palette load routines for Direct Color support. -jens */
|
|
if (pScrn->bitsPerPixel == 16) {
|
|
if (pScrn->depth == 15) {
|
|
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, NULL,
|
|
CMAP_PALETTED_TRUECOLOR |
|
|
CMAP_RELOAD_ON_MODE_SWITCH))
|
|
return FALSE;
|
|
} else {
|
|
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, NULL,
|
|
CMAP_PALETTED_TRUECOLOR |
|
|
CMAP_RELOAD_ON_MODE_SWITCH))
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, NULL,
|
|
CMAP_PALETTED_TRUECOLOR |
|
|
CMAP_RELOAD_ON_MODE_SWITCH))
|
|
return FALSE;
|
|
}
|
|
|
|
xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0);
|
|
|
|
I810InitVideo(pScreen);
|
|
|
|
#ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
/* Now that mi, fb, drm and others have done their thing,
|
|
* complete the DRI setup.
|
|
*/
|
|
pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
|
|
}
|
|
#ifdef XvMCExtension
|
|
if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
|
|
/* Initialize the hardware motion compensation code */
|
|
I810InitMC(pScreen);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (pI810->directRenderingEnabled) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
|
|
}
|
|
|
|
pScreen->SaveScreen = I810SaveScreen;
|
|
pI810->CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = I810CloseScreen;
|
|
|
|
if (serverGeneration == 1)
|
|
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
#if 0
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
#endif
|
|
if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
|
|
ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags);
|
|
|
|
#if 0
|
|
/*
|
|
* This has been added to prevent lockups on mode switch by modeling
|
|
* it after I810Leave()/I810Enter() but the call to I810DRILeave()
|
|
* was missing so it caused the opposite.
|
|
* The version below works but it is doubtful it does any good.
|
|
* If lockups on mode switch are still seen revisit this code. (EE)
|
|
*/
|
|
|
|
# ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("calling dri lock\n");
|
|
DRILock(screenInfo.screens[scrnIndex], 0);
|
|
pI810->LockHeld = 1;
|
|
}
|
|
# endif
|
|
if (pI810->AccelInfoRec != NULL) {
|
|
I810RefreshRing(pScrn);
|
|
I810Sync(pScrn);
|
|
pI810->AccelInfoRec->NeedToSync = FALSE;
|
|
}
|
|
I810Restore(pScrn);
|
|
|
|
# ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
if (!I810DRILeave(pScrn))
|
|
return FALSE;
|
|
if (!I810DRIEnter(pScrn))
|
|
return FALSE;
|
|
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("calling dri unlock\n");
|
|
DRIUnlock(screenInfo.screens[scrnIndex]);
|
|
pI810->LockHeld = 0;
|
|
}
|
|
# endif
|
|
#endif
|
|
return I810ModeInit(pScrn, mode);
|
|
}
|
|
|
|
void
|
|
I810AdjustFrame(int scrnIndex, int x, int y, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
int Base;
|
|
|
|
#if 1
|
|
if (pI810->showCache) {
|
|
int lastline = pI810->FbMapSize /
|
|
((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
|
|
lastline -= pScrn->currentMode->VDisplay;
|
|
if (y > 0)
|
|
y += pScrn->currentMode->VDisplay;
|
|
if (y > lastline) y = lastline;
|
|
}
|
|
#endif
|
|
Base = (y * pScrn->displayWidth + x) >> 2;
|
|
|
|
if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
|
|
ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags);
|
|
|
|
switch (pScrn->bitsPerPixel) {
|
|
case 8:
|
|
break;
|
|
case 16:
|
|
Base *= 2;
|
|
break;
|
|
case 24:
|
|
/* KW: Need to do 16-pixel alignment for i810, otherwise you
|
|
* get bad watermark problems. Need to fixup the mouse
|
|
* pointer positioning to take this into account.
|
|
*/
|
|
pI810->CursorOffset = (Base & 0x3) * 4;
|
|
Base &= ~0x3;
|
|
Base *= 3;
|
|
break;
|
|
case 32:
|
|
Base *= 4;
|
|
break;
|
|
}
|
|
|
|
hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF);
|
|
hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8);
|
|
hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22);
|
|
hwp->writeCrtc(hwp, EXT_START_ADDR,
|
|
((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE));
|
|
}
|
|
|
|
/* These functions are usually called with the lock **not held**.
|
|
*/
|
|
static Bool
|
|
I810EnterVT(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
|
|
#ifdef XF86DRI
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
#endif
|
|
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("\n\nENTER VT\n");
|
|
|
|
if (!I810BindGARTMemory(pScrn)) {
|
|
return FALSE;
|
|
}
|
|
#ifdef XF86DRI
|
|
if (!I810DRIEnter(pScrn)) {
|
|
return FALSE;
|
|
}
|
|
if (pI810->directRenderingEnabled) {
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("calling dri unlock\n");
|
|
DRIUnlock(screenInfo.screens[scrnIndex]);
|
|
pI810->LockHeld = 0;
|
|
}
|
|
#endif
|
|
|
|
if (!I810ModeInit(pScrn, pScrn->currentMode))
|
|
return FALSE;
|
|
I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
I810LeaveVT(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("\n\n\nLeave VT\n");
|
|
|
|
#ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
|
|
ErrorF("calling dri lock\n");
|
|
DRILock(screenInfo.screens[scrnIndex], 0);
|
|
pI810->LockHeld = 1;
|
|
}
|
|
#endif
|
|
|
|
if (pI810->AccelInfoRec != NULL) {
|
|
I810RefreshRing(pScrn);
|
|
I810Sync(pScrn);
|
|
pI810->AccelInfoRec->NeedToSync = FALSE;
|
|
}
|
|
I810Restore(pScrn);
|
|
|
|
if (!I810UnbindGARTMemory(pScrn))
|
|
return;
|
|
#ifdef XF86DRI
|
|
if (!I810DRILeave(pScrn))
|
|
return;
|
|
#endif
|
|
|
|
vgaHWLock(hwp);
|
|
}
|
|
|
|
static Bool
|
|
I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
I810Ptr pI810 = I810PTR(pScrn);
|
|
XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
|
|
|
|
if (pScrn->vtSema == TRUE) {
|
|
if (pI810->AccelInfoRec != NULL) {
|
|
I810RefreshRing(pScrn);
|
|
I810Sync(pScrn);
|
|
pI810->AccelInfoRec->NeedToSync = FALSE;
|
|
}
|
|
I810Restore(pScrn);
|
|
vgaHWLock(hwp);
|
|
}
|
|
#ifdef XF86DRI
|
|
if (pI810->directRenderingEnabled) {
|
|
I810DRICloseScreen(pScreen);
|
|
pI810->directRenderingEnabled = FALSE;
|
|
}
|
|
#endif
|
|
|
|
if (pScrn->vtSema == TRUE) {
|
|
I810UnbindGARTMemory(pScrn);
|
|
I810Restore(pScrn);
|
|
vgaHWLock(hwp);
|
|
}
|
|
|
|
I810UnmapMem(pScrn);
|
|
vgaHWUnmapMem(pScrn);
|
|
|
|
if (pI810->ScanlineColorExpandBuffers) {
|
|
xfree(pI810->ScanlineColorExpandBuffers);
|
|
pI810->ScanlineColorExpandBuffers = NULL;
|
|
}
|
|
|
|
if (infoPtr) {
|
|
if (infoPtr->ScanlineColorExpandBuffers)
|
|
xfree(infoPtr->ScanlineColorExpandBuffers);
|
|
XAADestroyInfoRec(infoPtr);
|
|
pI810->AccelInfoRec = NULL;
|
|
}
|
|
|
|
if (pI810->CursorInfoRec) {
|
|
xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
|
|
pI810->CursorInfoRec = NULL;
|
|
}
|
|
|
|
/* Free all allocated video ram.
|
|
*/
|
|
pI810->SysMem = pI810->SavedSysMem;
|
|
pI810->DcacheMem = pI810->SavedDcacheMem;
|
|
pI810->DoneFrontAlloc = FALSE;
|
|
|
|
/* Need to actually close the gart fd, or the unbound memory will just sit
|
|
* around. Will prevent the Xserver from recycling.
|
|
*/
|
|
xf86GARTCloseScreen(scrnIndex);
|
|
|
|
xfree(pI810->LpRing);
|
|
pI810->LpRing = NULL;
|
|
|
|
pScrn->vtSema = FALSE;
|
|
pScreen->CloseScreen = pI810->CloseScreen;
|
|
return (*pScreen->CloseScreen) (scrnIndex, pScreen);
|
|
}
|
|
|
|
static void
|
|
I810FreeScreen(int scrnIndex, int flags)
|
|
{
|
|
I810FreeRec(xf86Screens[scrnIndex]);
|
|
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
|
|
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
static ModeStatus
|
|
I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
|
|
{
|
|
if (mode->Flags & V_INTERLACE) {
|
|
if (verbose) {
|
|
xf86DrvMsg(scrnIndex, X_PROBED,
|
|
"Removing interlaced mode \"%s\"\n", mode->name);
|
|
}
|
|
return MODE_BAD;
|
|
}
|
|
return MODE_OK;
|
|
}
|
|
|
|
static Bool
|
|
I810SaveScreen(ScreenPtr pScreen, Bool unblack)
|
|
{
|
|
return vgaHWSaveScreen(pScreen, unblack);
|
|
}
|
|
|
|
static void
|
|
I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
|
|
int flags)
|
|
{
|
|
I810Ptr pI810;
|
|
unsigned char SEQ01 = 0;
|
|
int DPMSSyncSelect = 0;
|
|
|
|
pI810 = I810PTR(pScrn);
|
|
switch (PowerManagementMode) {
|
|
case DPMSModeOn:
|
|
/* Screen: On; HSync: On, VSync: On */
|
|
SEQ01 = 0x00;
|
|
DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
|
|
break;
|
|
case DPMSModeStandby:
|
|
/* Screen: Off; HSync: Off, VSync: On */
|
|
SEQ01 = 0x20;
|
|
DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
|
|
break;
|
|
case DPMSModeSuspend:
|
|
/* Screen: Off; HSync: On, VSync: Off */
|
|
SEQ01 = 0x20;
|
|
DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
|
|
break;
|
|
case DPMSModeOff:
|
|
/* Screen: Off; HSync: Off, VSync: Off */
|
|
SEQ01 = 0x20;
|
|
DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
|
|
break;
|
|
}
|
|
|
|
/* Turn the screen on/off */
|
|
SEQ01 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20;
|
|
pI810->writeControl(pI810, SRX, 0x01, SEQ01);
|
|
|
|
/* Set the DPMS mode */
|
|
OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
|
|
}
|
|
#endif /* I830_ONLY */
|