mirror of
https://github.com/X11Libre/xf86-video-xgi.git
synced 2026-03-24 01:24:35 +00:00
Shuffle files around into their correct places. Create Makefile.am, configure.ac, and autogen.sh based on similar files in other drivers. Delete pre-modular files (e.g., Imakefile) that are no longer necessary.
8093 lines
215 KiB
C
8093 lines
215 KiB
C
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/xgi_driver.c,v 1.185 2004/02/27 17:29:24 twini Exp $ */
|
|
/*
|
|
* XGI driver main code
|
|
*
|
|
* Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1) Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2) 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.
|
|
* 3) The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR 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.
|
|
*
|
|
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
|
* - driver entirely rewritten since 2001, only basic structure taken from
|
|
* old code (except xgi_dri.c, xgi_shadow.c, xgi_accel.c and parts of
|
|
* xgi_dga.c; these were mostly taken over; xgi_dri.c was changed for
|
|
* new versions of the DRI layer)
|
|
*
|
|
* This notice covers the entire driver code unless otherwise indicated.
|
|
*
|
|
* Formerly based on code which is
|
|
* Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
|
|
* Written by:
|
|
* Alan Hourihane <alanh@fairlite.demon.co.uk>,
|
|
* Mike Chapman <mike@paranoia.com>,
|
|
* Juanjo Santamarta <santamarta@ctv.es>,
|
|
* Mitani Hiroshi <hmitani@drl.mei.co.jp>,
|
|
* David Thomas <davtom@dream.org.uk>.
|
|
*/
|
|
|
|
#include "fb.h"
|
|
#include "mibank.h"
|
|
#include "micmap.h"
|
|
#include "xf86.h"
|
|
#include "xf86Priv.h"
|
|
#include "xf86_OSproc.h"
|
|
#include "xf86Resources.h"
|
|
#include "xf86_ansic.h"
|
|
#include "dixstruct.h"
|
|
#include "xf86Version.h"
|
|
#include "xf86PciInfo.h"
|
|
#include "xf86Pci.h"
|
|
#include "xf86cmap.h"
|
|
#include "vgaHW.h"
|
|
#include "xf86RAC.h"
|
|
#include "shadowfb.h"
|
|
#include "vbe.h"
|
|
|
|
#include "mipointer.h"
|
|
#include "mibstore.h"
|
|
|
|
#include "xgi.h"
|
|
#include "regs.h"
|
|
#include "xgi_vb.h"
|
|
#include "xgi_dac.h"
|
|
#include "initdef.h"
|
|
#include "xgi_driver.h"
|
|
#include "valid_mode.h"
|
|
|
|
#define _XF86DGA_SERVER_
|
|
#include "extensions/xf86dgastr.h"
|
|
|
|
#include "globals.h"
|
|
|
|
#define DPMS_SERVER
|
|
#include "extensions/dpms.h"
|
|
|
|
#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension))
|
|
#include "xf86xv.h"
|
|
#include "Xv.h"
|
|
#endif
|
|
|
|
#ifdef XF86DRI
|
|
#include "dri.h"
|
|
#endif
|
|
|
|
void Volari_EnableAccelerator(ScrnInfoPtr pScrn) ;
|
|
/* Globals (yes, these ARE really required to be global) */
|
|
|
|
#ifdef XGIDUALHEAD
|
|
static int XGIEntityIndex = -1;
|
|
#endif
|
|
|
|
/* Jong Lin 08-26-2005; keep current mode info */
|
|
unsigned int CurrentHDisplay;
|
|
unsigned int CurrentVDisplay;
|
|
unsigned int CurrentColorDepth;
|
|
|
|
/*
|
|
* This is intentionally screen-independent. It indicates the binding
|
|
* choice made in the first PreInit.
|
|
*/
|
|
static int pix24bpp = 0;
|
|
int FbDevExist;
|
|
|
|
#define FBIOGET_FSCREENINFO 0x4602
|
|
#define FB_ACCEL_XGI_GLAMOUR 41
|
|
|
|
struct fb_fix_screeninfo {
|
|
char id[16]; /* identification string eg "TT Builtin" */
|
|
unsigned long smem_start; /* Start of frame buffer mem */
|
|
/* (physical address) */
|
|
unsigned long smem_len; /* Length of frame buffer mem */
|
|
unsigned long type; /* see FB_TYPE_* */
|
|
unsigned long type_aux; /* Interleave for interleaved Planes */
|
|
unsigned long visual; /* see FB_VISUAL_* */
|
|
unsigned short xpanstep; /* zero if no hardware panning */
|
|
unsigned short ypanstep; /* zero if no hardware panning */
|
|
unsigned short ywrapstep; /* zero if no hardware ywrap */
|
|
unsigned long line_length; /* length of a line in bytes */
|
|
unsigned long mmio_start; /* Start of Memory Mapped I/O */
|
|
/* (physical address) */
|
|
unsigned long mmio_len; /* Length of Memory Mapped I/O */
|
|
unsigned long accel; /* Type of acceleration available */
|
|
unsigned short reserved[3]; /* Reserved for future compatibility */
|
|
};
|
|
|
|
/*
|
|
* This contains the functions needed by the server after loading the driver
|
|
* module. It must be supplied, and gets passed back by the SetupProc
|
|
* function in the dynamic case. In the static case, a reference to this
|
|
* is compiled in, and this requires that the name of this DriverRec be
|
|
* an upper-case version of the driver name.
|
|
*/
|
|
|
|
DriverRec XGI = {
|
|
XGI_CURRENT_VERSION,
|
|
XGI_DRIVER_NAME,
|
|
XGIIdentify,
|
|
XGIProbe,
|
|
XGIAvailableOptions,
|
|
NULL,
|
|
0
|
|
};
|
|
|
|
static SymTabRec XGIChipsets[] = {
|
|
{ PCI_CHIP_XGIXG40, "Volari V8_V5_V3XT" },
|
|
{ PCI_CHIP_XGIXG20, "Volari Z7" },
|
|
{ -1, NULL }
|
|
};
|
|
|
|
static PciChipsets XGIPciChipsets[] = {
|
|
{ PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA },
|
|
{ PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA },
|
|
{ -1, -1, RES_UNDEFINED }
|
|
};
|
|
|
|
static const char *xaaSymbols[] = {
|
|
"XAACopyROP",
|
|
"XAACreateInfoRec",
|
|
"XAADestroyInfoRec",
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
|
|
"XAAFillSolidRects",
|
|
#endif
|
|
"XAAFillMono8x8PatternRects",
|
|
"XAAPatternROP",
|
|
"XAAHelpPatternROP",
|
|
"XAAInit",
|
|
NULL
|
|
};
|
|
|
|
static const char *vgahwSymbols[] = {
|
|
"vgaHWFreeHWRec",
|
|
"vgaHWGetHWRec",
|
|
"vgaHWGetIOBase",
|
|
"vgaHWGetIndex",
|
|
"vgaHWInit",
|
|
"vgaHWLock",
|
|
"vgaHWMapMem",
|
|
"vgaHWUnmapMem",
|
|
"vgaHWProtect",
|
|
"vgaHWRestore",
|
|
"vgaHWSave",
|
|
"vgaHWSaveScreen",
|
|
"vgaHWUnlock",
|
|
NULL
|
|
};
|
|
|
|
static const char *fbSymbols[] = {
|
|
"fbPictureInit",
|
|
"fbScreenInit",
|
|
NULL
|
|
};
|
|
|
|
static const char *shadowSymbols[] = {
|
|
"ShadowFBInit",
|
|
NULL
|
|
};
|
|
|
|
static const char *ramdacSymbols[] = {
|
|
"xf86CreateCursorInfoRec",
|
|
"xf86DestroyCursorInfoRec",
|
|
"xf86InitCursor",
|
|
NULL
|
|
};
|
|
|
|
|
|
static const char *ddcSymbols[] = {
|
|
"xf86PrintEDID",
|
|
"xf86SetDDCproperties",
|
|
"xf86InterpretEDID",
|
|
NULL
|
|
};
|
|
|
|
|
|
/* static const char *i2cSymbols[] = {
|
|
"xf86I2CBusInit",
|
|
"xf86CreateI2CBusRec",
|
|
NULL
|
|
}; */
|
|
|
|
static const char *int10Symbols[] = {
|
|
"xf86FreeInt10",
|
|
"xf86InitInt10",
|
|
"xf86ExecX86int10",
|
|
NULL
|
|
};
|
|
|
|
static const char *vbeSymbols[] = {
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
"VBEInit",
|
|
#else
|
|
"VBEExtendedInit",
|
|
#endif
|
|
"vbeDoEDID",
|
|
"vbeFree",
|
|
"VBEGetVBEInfo",
|
|
"VBEFreeVBEInfo",
|
|
"VBEGetModeInfo",
|
|
"VBEFreeModeInfo",
|
|
"VBESaveRestore",
|
|
"VBESetVBEMode",
|
|
"VBEGetVBEMode",
|
|
"VBESetDisplayStart",
|
|
"VBESetGetLogicalScanlineLength",
|
|
NULL
|
|
};
|
|
|
|
#ifdef XF86DRI
|
|
static const char *drmSymbols[] = {
|
|
"drmAddMap",
|
|
"drmAgpAcquire",
|
|
"drmAgpAlloc",
|
|
"drmAgpBase",
|
|
"drmAgpBind",
|
|
"drmAgpEnable",
|
|
"drmAgpFree",
|
|
"drmAgpGetMode",
|
|
"drmAgpRelease",
|
|
"drmCtlInstHandler",
|
|
"drmGetInterruptFromBusID",
|
|
"drmXGIAgpInit",
|
|
NULL
|
|
};
|
|
|
|
static const char *driSymbols[] = {
|
|
"DRICloseScreen",
|
|
"DRICreateInfoRec",
|
|
"DRIDestroyInfoRec",
|
|
"DRIFinishScreenInit",
|
|
"DRIGetSAREAPrivate",
|
|
"DRILock",
|
|
"DRIQueryVersion",
|
|
"DRIScreenInit",
|
|
"DRIUnlock",
|
|
#ifdef XGINEWDRI2
|
|
"GlxSetVisualConfigs",
|
|
"DRICreatePCIBusID",
|
|
#endif
|
|
NULL
|
|
};
|
|
#endif
|
|
|
|
#ifdef XFree86LOADER
|
|
|
|
static MODULESETUPPROTO(xgiSetup);
|
|
|
|
static XF86ModuleVersionInfo xgiVersRec =
|
|
{
|
|
XGI_DRIVER_NAME,
|
|
MODULEVENDORSTRING,
|
|
MODINFOSTRING1,
|
|
MODINFOSTRING2,
|
|
XF86_VERSION_CURRENT,
|
|
XGI_MAJOR_VERSION, XGI_MINOR_VERSION, XGI_PATCHLEVEL,
|
|
ABI_CLASS_VIDEODRV, /* This is a video driver */
|
|
6,
|
|
MOD_CLASS_VIDEODRV,
|
|
{0,0,0,0}
|
|
};
|
|
|
|
XF86ModuleData xgiModuleData = { &xgiVersRec, xgiSetup, NULL };
|
|
|
|
/*** static string ***/
|
|
#ifdef XGIMERGED
|
|
static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n";
|
|
static const char *mergednocrt2 = "No CRT2 output selected or no bridge detected. %s.\n";
|
|
static const char *mergeddisstr = "MergedFB mode disabled";
|
|
static const char *modesforstr = "Modes for CRT%d: *********************************************\n";
|
|
static const char *crtsetupstr = "------------------------ CRT%d setup -------------------------\n";
|
|
#endif
|
|
/*
|
|
#if defined(XGIDUALHEAD) || defined(XGIMERGED)
|
|
static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n";
|
|
#endif
|
|
*/
|
|
|
|
/* 2005/11/09 added by jjtseng */
|
|
static void XGISavePrevMode(ScrnInfoPtr pScrn) ;
|
|
static void XGIRestorePrevMode(ScrnInfoPtr pScrn) ;
|
|
/*~jjtseng 2005/11/09 */
|
|
int DumpDDIName(const char *fmt, ...) ;
|
|
|
|
typedef struct {
|
|
int width, height ;
|
|
float VRefresh,HSync,DCLK ;
|
|
} ModeTiming ;
|
|
|
|
ModeTiming establish_timing[] = {
|
|
{800,600,60,37.9,40},/* t1 D[0] */
|
|
{800,600,56,35.1,36},/* t1 D[1] */
|
|
{640,480,75,37.5,31.5},/* t1 D[2] */
|
|
{640,480,72,37.9,31.5},/* t1 D[3] */
|
|
{-1,-1,-1,-1},/* t1 D[4] 640x480@67Hz, ignore*/
|
|
{640,480,60,31.5,25.175},/* t1 D[5] */
|
|
{-1,-1,-1,-1},/* t1 D[6] */
|
|
{-1,-1,-1,-1},/* t1 D[7] */
|
|
{1280,1024,75,80.0,135},/* t2 D[0] */
|
|
{1024,768,75,60.0,78.75},/* t2 D[1] */
|
|
{1024,768,70,56.5,75},/* t2 D[2] */
|
|
{1024,768,60,48.4,65},/* t2 D[3] */
|
|
{-1,-1,-1,-1},/* t2 D[4] 1024x768@87I, ignore */
|
|
{-1,-1,-1,-1},/* t2 D[5] 832x624@75Hz, ignore*/
|
|
{800,600,75,46.9,49.5},/* t2 D[6] */
|
|
{800,600,72,48.1,50}/* t2 D[7] */
|
|
} ;
|
|
|
|
ModeTiming StdTiming[] = {
|
|
{640,480,60,31.5,25.175},
|
|
{640,480,72,37.9,31.5},
|
|
{640,480,75,37.5,31.5},
|
|
{640,480,85,43.3,36.0},
|
|
|
|
{800,600,56,35.1,36},
|
|
{800,600,60,37.9,40},
|
|
{800,600,72,48.1,50},
|
|
{800,600,75,46.9,49.5},
|
|
{800,600,85,53.7,56.25},
|
|
|
|
{1024,768,43,35.5,44.9},
|
|
{1024,768,60,48.4,65},
|
|
{1024,768,70,56.5,75},
|
|
{1024,768,75,60,78.75},
|
|
{1024,768,85,68.7,94.5},
|
|
|
|
{1152,864,75,67.5,108},
|
|
|
|
{1280,960,60,60,108},
|
|
{1280,960,85,85.9,148.5},
|
|
{1280,1024,60,64.0,108},
|
|
{1280,1024,75,80,135},
|
|
{1280,1024,85,91.1,157.5},
|
|
|
|
{1600,1200,60,75,162.0},
|
|
{1600,1200,65,81.3,175.5},
|
|
{1600,1200,70,87.5,189},
|
|
{1600,1200,75,93.8,202},
|
|
{1600,1200,85,106.3,229.5},
|
|
|
|
{1792,1344,60,83.64,204.75},
|
|
{1792,1344,75,106.27,261},
|
|
|
|
{1856,1392,60,86.33,218.25},
|
|
{1856,1392,75,112.50,288},
|
|
|
|
{1920,1440,60,90,234},
|
|
{1920,1440,75,112.5,297},
|
|
{-1,-1,-1,-1,-1},
|
|
} ;
|
|
|
|
|
|
pointer
|
|
xgiSetup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = FALSE;
|
|
|
|
if(!setupDone)
|
|
{
|
|
setupDone = TRUE;
|
|
xf86AddDriver(&XGI, module, 0);
|
|
LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
|
|
shadowSymbols, ramdacSymbols, ddcSymbols,
|
|
vbeSymbols, int10Symbols,
|
|
#ifdef XF86DRI
|
|
drmSymbols, driSymbols,
|
|
#endif
|
|
NULL);
|
|
return (pointer)TRUE;
|
|
}
|
|
|
|
if(errmaj) *errmaj = LDR_ONCEONLY;
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* XFree86LOADER */
|
|
|
|
|
|
static Bool
|
|
XGIGetRec(ScrnInfoPtr pScrn)
|
|
{
|
|
/*
|
|
* Allocate an XGIRec, and hook it into pScrn->driverPrivate.
|
|
* pScrn->driverPrivate is initialised to NULL, so we can check if
|
|
* the allocation has already been done.
|
|
*/
|
|
if(pScrn->driverPrivate != NULL) return TRUE;
|
|
|
|
pScrn->driverPrivate = xnfcalloc(sizeof(XGIRec), 1);
|
|
|
|
/* Initialise it to 0 */
|
|
memset(pScrn->driverPrivate, 0, sizeof(XGIRec));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
XGIFreeRec(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = NULL;
|
|
#endif
|
|
|
|
/* Just to make sure... */
|
|
if(!pXGI) return;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
pXGIEnt = pXGI->entityPrivate;
|
|
#endif
|
|
|
|
if(pXGI->pstate) xfree(pXGI->pstate);
|
|
pXGI->pstate = NULL;
|
|
if(pXGI->fonts) xfree(pXGI->fonts);
|
|
pXGI->fonts = NULL;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt)
|
|
{
|
|
if(!pXGI->SecondHead)
|
|
{
|
|
/* Free memory only if we are first head; in case of an error
|
|
* during init of the second head, the server will continue -
|
|
* and we need the BIOS image and XGI_Private for the first
|
|
* head.
|
|
*/
|
|
if(pXGIEnt->BIOS) xfree(pXGIEnt->BIOS);
|
|
pXGIEnt->BIOS = pXGI->BIOS = NULL;
|
|
if(pXGIEnt->XGI_Pr) xfree(pXGIEnt->XGI_Pr);
|
|
pXGIEnt->XGI_Pr = pXGI->XGI_Pr = NULL;
|
|
if(pXGIEnt->RenderAccelArray) xfree(pXGIEnt->RenderAccelArray);
|
|
pXGIEnt->RenderAccelArray = pXGI->RenderAccelArray = NULL;
|
|
}
|
|
else
|
|
{
|
|
pXGI->BIOS = NULL;
|
|
pXGI->XGI_Pr = NULL;
|
|
pXGI->RenderAccelArray = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if(pXGI->BIOS) xfree(pXGI->BIOS);
|
|
pXGI->BIOS = NULL;
|
|
if(pXGI->XGI_Pr) xfree(pXGI->XGI_Pr);
|
|
pXGI->XGI_Pr = NULL;
|
|
if(pXGI->RenderAccelArray) xfree(pXGI->RenderAccelArray);
|
|
pXGI->RenderAccelArray = NULL;
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
#ifdef XGIMERGED
|
|
|
|
if(pXGI->MetaModes) xfree(pXGI->MetaModes);
|
|
pXGI->MetaModes = NULL;
|
|
|
|
if(pXGI->CRT1Modes)
|
|
{
|
|
if(pXGI->CRT1Modes != pScrn->modes)
|
|
{
|
|
if(pScrn->modes)
|
|
{
|
|
pScrn->currentMode = pScrn->modes;
|
|
do
|
|
{
|
|
DisplayModePtr p = pScrn->currentMode->next;
|
|
if(pScrn->currentMode->Private)
|
|
xfree(pScrn->currentMode->Private);
|
|
xfree(pScrn->currentMode);
|
|
pScrn->currentMode = p;
|
|
}
|
|
while(pScrn->currentMode != pScrn->modes);
|
|
}
|
|
pScrn->currentMode = pXGI->CRT1CurrentMode;
|
|
pScrn->modes = pXGI->CRT1Modes;
|
|
pXGI->CRT1CurrentMode = NULL;
|
|
pXGI->CRT1Modes = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
if(pXGI->pVbe) vbeFree(pXGI->pVbe);
|
|
pXGI->pVbe = NULL;
|
|
if(pScrn->driverPrivate == NULL)
|
|
return;
|
|
xfree(pScrn->driverPrivate);
|
|
pScrn->driverPrivate = NULL;
|
|
}
|
|
|
|
static void
|
|
XGIDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
BOOLEAN docrt1 = TRUE, docrt2 = TRUE;
|
|
unsigned char sr1=0, cr17=0, cr63=0, sr11=0, pmreg=0, sr7=0;
|
|
unsigned char p1_13=0, p2_0=0, oldpmreg=0;
|
|
BOOLEAN backlight = TRUE;
|
|
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
|
|
"XGIDisplayPowerManagementSet(%d)\n",PowerManagementMode);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->SecondHead) docrt2 = FALSE;
|
|
else docrt1 = FALSE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
#endif
|
|
|
|
switch (PowerManagementMode)
|
|
{
|
|
|
|
case DPMSModeOn: /* HSync: On, VSync: On */
|
|
if(docrt1) pXGI->Blank = FALSE;
|
|
#ifdef XGIDUALHEAD
|
|
else pXGI->BlankCRT2 = FALSE;
|
|
#endif
|
|
sr1 = 0x00;
|
|
cr17 = 0x80;
|
|
pmreg = 0x00;
|
|
cr63 = 0x00;
|
|
sr7 = 0x10;
|
|
sr11 = (pXGI->LCDon & 0x0C);
|
|
p2_0 = 0x20;
|
|
p1_13 = 0x00;
|
|
backlight = TRUE;
|
|
break;
|
|
|
|
case DPMSModeSuspend: /* HSync: On, VSync: Off */
|
|
if(docrt1) pXGI->Blank = TRUE;
|
|
#ifdef XGIDUALHEAD
|
|
else pXGI->BlankCRT2 = TRUE;
|
|
#endif
|
|
sr1 = 0x20;
|
|
cr17 = 0x80;
|
|
pmreg = 0x80;
|
|
cr63 = 0x40;
|
|
sr7 = 0x00;
|
|
sr11 = 0x08;
|
|
p2_0 = 0x40;
|
|
p1_13 = 0x80;
|
|
backlight = FALSE;
|
|
break;
|
|
|
|
case DPMSModeStandby: /* HSync: Off, VSync: On */
|
|
if(docrt1) pXGI->Blank = TRUE;
|
|
#ifdef XGIDUALHEAD
|
|
else pXGI->BlankCRT2 = TRUE;
|
|
#endif
|
|
sr1 = 0x20;
|
|
cr17 = 0x80;
|
|
pmreg = 0x40;
|
|
cr63 = 0x40;
|
|
sr7 = 0x00;
|
|
sr11 = 0x08;
|
|
p2_0 = 0x80;
|
|
p1_13 = 0x40;
|
|
backlight = FALSE;
|
|
break;
|
|
|
|
case DPMSModeOff: /* HSync: Off, VSync: Off */
|
|
if(docrt1) pXGI->Blank = TRUE;
|
|
#ifdef XGIDUALHEAD
|
|
else pXGI->BlankCRT2 = TRUE;
|
|
#endif
|
|
sr1 = 0x20;
|
|
cr17 = 0x00;
|
|
pmreg = 0xc0;
|
|
cr63 = 0x40;
|
|
sr7 = 0x00;
|
|
sr11 = 0x08;
|
|
p2_0 = 0xc0;
|
|
p1_13 = 0xc0;
|
|
backlight = FALSE;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if(docrt1)
|
|
{
|
|
setXGIIDXREG(XGISR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */
|
|
switch(pXGI->VGAEngine)
|
|
{
|
|
case XGI_OLD_VGA:
|
|
inXGIIDXREG(XGISR, 0x11, oldpmreg);
|
|
setXGIIDXREG(XGICR, 0x17, 0x7f, cr17);
|
|
setXGIIDXREG(XGISR, 0x11, 0x3f, pmreg);
|
|
break;
|
|
/* fall through */
|
|
default:
|
|
if((!(pXGI->VBFlags & CRT1_LCDA)) || (pXGI->XGI_Pr->XGI_VBType & VB_XGI301C))
|
|
{
|
|
inXGIIDXREG(XGISR, 0x1f, oldpmreg);
|
|
if(!pXGI->CRT1off)
|
|
{
|
|
setXGIIDXREG(XGISR, 0x1f, 0x3f, pmreg);
|
|
}
|
|
}
|
|
/* TODO: Check if Chrontel TV is active and in slave mode,
|
|
* don't go into power-saving mode this in this case!
|
|
*/
|
|
}
|
|
oldpmreg &= 0xc0;
|
|
}
|
|
|
|
if((docrt1) && (pmreg != oldpmreg) && ((!(pXGI->VBFlags & CRT1_LCDA)) || (pXGI->XGI_Pr->XGI_VBType & VB_XGI301C)))
|
|
{
|
|
outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
|
|
usleep(10000);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
|
|
}
|
|
|
|
}
|
|
|
|
/* Mandatory */
|
|
static void
|
|
XGIIdentify(int flags)
|
|
{
|
|
xf86PrintChipsets(XGI_NAME, "driver for XGI chipsets", XGIChipsets);
|
|
PDEBUG(ErrorF(" --- XGIIdentify \n"));
|
|
}
|
|
|
|
static void
|
|
XGIErrorLog(ScrnInfoPtr pScrn, const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
static const char *str = "**************************************************\n";
|
|
|
|
va_start(ap, format);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
" ERROR:\n");
|
|
xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap);
|
|
va_end(ap);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
" END OF MESSAGE\n");
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str);
|
|
}
|
|
|
|
/* Mandatory */
|
|
static Bool
|
|
XGIProbe(DriverPtr drv, int flags)
|
|
{
|
|
int i;
|
|
GDevPtr *devSections;
|
|
int *usedChips;
|
|
int numDevSections;
|
|
int numUsed;
|
|
Bool foundScreen = FALSE;
|
|
|
|
/*
|
|
* The aim here is to find all cards that this driver can handle,
|
|
* and for the ones not already claimed by another driver, claim the
|
|
* slot, and allocate a ScrnInfoRec.
|
|
*
|
|
* This should be a minimal probe, and it should under no circumstances
|
|
* change the state of the hardware. Because a device is found, don't
|
|
* assume that it will be used. Don't do any initialisations other than
|
|
* the required ScrnInfoRec initialisations. Don't allocate any new
|
|
* data structures.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Next we check, if there has been a chipset override in the config file.
|
|
* For this we must find out if there is an active device section which
|
|
* is relevant, i.e., which has no driver specified or has THIS driver
|
|
* specified.
|
|
*/
|
|
|
|
if((numDevSections = xf86MatchDevice(XGI_DRIVER_NAME, &devSections)) <= 0)
|
|
{
|
|
/*
|
|
* There's no matching device section in the config file, so quit
|
|
* now.
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
PDEBUG(ErrorF(" --- XGIProbe \n"));
|
|
/*
|
|
* We need to probe the hardware first. We then need to see how this
|
|
* fits in with what is given in the config file, and allow the config
|
|
* file info to override any contradictions.
|
|
*/
|
|
|
|
/*
|
|
* All of the cards this driver supports are PCI, so the "probing" just
|
|
* amounts to checking the PCI data that the server has already collected.
|
|
*/
|
|
if(xf86GetPciVideoInfo() == NULL)
|
|
{
|
|
/*
|
|
* We won't let anything in the config file override finding no
|
|
* PCI video cards at all. This seems reasonable now, but we'll see.
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
numUsed = xf86MatchPciInstances(XGI_NAME, PCI_VENDOR_XGI,
|
|
XGIChipsets, XGIPciChipsets, devSections,
|
|
numDevSections, drv, &usedChips);
|
|
|
|
/* Free it since we don't need that list after this */
|
|
xfree(devSections);
|
|
if(numUsed <= 0) return FALSE;
|
|
|
|
if(flags & PROBE_DETECT)
|
|
{
|
|
foundScreen = TRUE;
|
|
}
|
|
else for(i = 0; i < numUsed; i++)
|
|
{
|
|
ScrnInfoPtr pScrn;
|
|
#ifdef XGIDUALHEAD
|
|
EntityInfoPtr pEnt;
|
|
#endif
|
|
|
|
/* Allocate a ScrnInfoRec and claim the slot */
|
|
pScrn = NULL;
|
|
|
|
if((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
|
|
XGIPciChipsets, NULL, NULL,
|
|
NULL, NULL, NULL)))
|
|
{
|
|
/* Fill in what we can of the ScrnInfoRec */
|
|
pScrn->driverVersion = XGI_CURRENT_VERSION;
|
|
pScrn->driverName = XGI_DRIVER_NAME;
|
|
pScrn->name = XGI_NAME;
|
|
pScrn->Probe = XGIProbe;
|
|
pScrn->PreInit = XGIPreInit;
|
|
pScrn->ScreenInit = XGIScreenInit;
|
|
pScrn->SwitchMode = XGISwitchMode;
|
|
pScrn->AdjustFrame = XGIAdjustFrame;
|
|
pScrn->EnterVT = XGIEnterVT;
|
|
pScrn->LeaveVT = XGILeaveVT;
|
|
pScrn->FreeScreen = XGIFreeScreen;
|
|
pScrn->ValidMode = XGIValidMode;
|
|
foundScreen = TRUE;
|
|
}
|
|
#ifdef XGIDUALHEAD
|
|
pEnt = xf86GetEntityInfo(usedChips[i]);
|
|
|
|
#endif
|
|
}
|
|
xfree(usedChips);
|
|
|
|
return foundScreen;
|
|
}
|
|
|
|
|
|
/* If monitor section has no HSync/VRefresh data,
|
|
* derive it from DDC data. Done by common layer
|
|
* since 4.3.99.14.
|
|
*/
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,14,0)
|
|
static void
|
|
XGISetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
|
|
{
|
|
MonPtr mon = pScrn->monitor;
|
|
xf86MonPtr ddc = mon->DDC;
|
|
int i,j;
|
|
float myhhigh, myhlow;
|
|
int myvhigh, myvlow;
|
|
unsigned char temp;
|
|
const myhddctiming myhtiming[11] =
|
|
{
|
|
{ 1, 0x20, 31.6 }, /* rounded up by .1 */
|
|
{ 1, 0x02, 35.3 },
|
|
{ 1, 0x04, 37.6 },
|
|
{ 1, 0x08, 38.0 },
|
|
{ 1, 0x01, 38.0 },
|
|
{ 2, 0x40, 47.0 },
|
|
{ 2, 0x80, 48.2 },
|
|
{ 2, 0x08, 48.5 },
|
|
{ 2, 0x04, 56.6 },
|
|
{ 2, 0x02, 60.1 },
|
|
{ 2, 0x01, 80.1 }
|
|
};
|
|
const myvddctiming myvtiming[10] =
|
|
{
|
|
{ 1, 0x02, 56 },
|
|
{ 1, 0x01, 60 },
|
|
{ 2, 0x08, 60 },
|
|
{ 2, 0x04, 70 },
|
|
{ 1, 0x08, 72 },
|
|
{ 2, 0x80, 72 },
|
|
{ 1, 0x04, 75 },
|
|
{ 2, 0x40, 75 },
|
|
{ 2, 0x02, 75 },
|
|
{ 2, 0x01, 75 }
|
|
};
|
|
/* "Future modes"; we only check the really high ones */
|
|
const myddcstdmodes mystdmodes[8] =
|
|
{
|
|
{ 1280, 1024, 85, 91.1 },
|
|
{ 1600, 1200, 60, 75.0 },
|
|
{ 1600, 1200, 65, 81.3 },
|
|
{ 1600, 1200, 70, 87.5 },
|
|
{ 1600, 1200, 75, 93.8 },
|
|
{ 1600, 1200, 85, 106.3 },
|
|
{ 1920, 1440, 60, 90.0 },
|
|
{ 1920, 1440, 75, 112.5 }
|
|
};
|
|
|
|
if(flag)
|
|
{ /* HSync */
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
if(ddc->det_mon[i].type == DS_RANGES)
|
|
{
|
|
mon->nHsync = 1;
|
|
mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h;
|
|
mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h;
|
|
return;
|
|
}
|
|
}
|
|
/* If no sync ranges detected in detailed timing table, we
|
|
* derive them from supported VESA modes. */
|
|
myhlow = myhhigh = 0.0;
|
|
for(i=0; i<11; i++)
|
|
{
|
|
if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1;
|
|
else temp = ddc->timings1.t2;
|
|
if(temp & myhtiming[i].mask)
|
|
{
|
|
if((i==0) || (myhlow > myhtiming[i].rate))
|
|
myhlow = myhtiming[i].rate;
|
|
}
|
|
if(myhtiming[10-i].whichone == 1) temp = ddc->timings1.t1;
|
|
else temp = ddc->timings1.t2;
|
|
if(temp & myhtiming[10-i].mask)
|
|
{
|
|
if((i==0) || (myhhigh < myhtiming[10-i].rate))
|
|
myhhigh = myhtiming[10-i].rate;
|
|
}
|
|
}
|
|
for(i=0;i<STD_TIMINGS;i++)
|
|
{
|
|
if(ddc->timings2[i].hsize > 256)
|
|
{
|
|
for(j=0; j<8; j++)
|
|
{
|
|
if((ddc->timings2[i].hsize == mystdmodes[j].hsize) &&
|
|
(ddc->timings2[i].vsize == mystdmodes[j].vsize) &&
|
|
(ddc->timings2[i].refresh == mystdmodes[j].refresh))
|
|
{
|
|
if(mystdmodes[j].hsync > myhhigh)
|
|
myhhigh = mystdmodes[j].hsync;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if((myhhigh) && (myhlow))
|
|
{
|
|
mon->nHsync = 1;
|
|
mon->hsync[0].lo = myhlow - 0.1;
|
|
mon->hsync[0].hi = myhhigh;
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{ /* Vrefresh */
|
|
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
if(ddc->det_mon[i].type == DS_RANGES)
|
|
{
|
|
mon->nVrefresh = 1;
|
|
mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v;
|
|
mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v;
|
|
return;
|
|
}
|
|
}
|
|
|
|
myvlow = myvhigh = 0;
|
|
for(i=0; i<10; i++)
|
|
{
|
|
if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1;
|
|
else temp = ddc->timings1.t2;
|
|
if(temp & myvtiming[i].mask)
|
|
{
|
|
if((i==0) || (myvlow > myvtiming[i].rate))
|
|
myvlow = myvtiming[i].rate;
|
|
}
|
|
if(myvtiming[9-i].whichone == 1) temp = ddc->timings1.t1;
|
|
else temp = ddc->timings1.t2;
|
|
if(temp & myvtiming[9-i].mask)
|
|
{
|
|
if((i==0) || (myvhigh < myvtiming[9-i].rate))
|
|
myvhigh = myvtiming[9-i].rate;
|
|
}
|
|
}
|
|
for(i=0;i<STD_TIMINGS;i++)
|
|
{
|
|
if(ddc->timings2[i].hsize > 256)
|
|
{
|
|
for(j=0; j<8; j++)
|
|
{
|
|
if((ddc->timings2[i].hsize == mystdmodes[j].hsize) &&
|
|
(ddc->timings2[i].vsize == mystdmodes[j].vsize) &&
|
|
(ddc->timings2[i].refresh == mystdmodes[j].refresh))
|
|
{
|
|
if(mystdmodes[j].refresh > myvhigh)
|
|
myvhigh = mystdmodes[j].refresh;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if((myvhigh) && (myvlow))
|
|
{
|
|
mon->nVrefresh = 1;
|
|
mon->vrefresh[0].lo = myvlow;
|
|
mon->vrefresh[0].hi = myvhigh;
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Some helper functions for MergedFB mode */
|
|
|
|
#ifdef XGIMERGED
|
|
|
|
/* Copy and link two modes form mergedfb mode
|
|
* (Code base taken from mga driver)
|
|
* Copys mode i, links the result to dest, and returns it.
|
|
* Links i and j in Private record.
|
|
* If dest is NULL, return value is copy of i linked to itself.
|
|
* For mergedfb auto-config, we only check the dimension
|
|
* against virtualX/Y, if they were user-provided.
|
|
*/
|
|
static DisplayModePtr
|
|
XGICopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
|
|
DisplayModePtr i, DisplayModePtr j,
|
|
XGIScrn2Rel srel)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
DisplayModePtr mode;
|
|
int dx = 0,dy = 0;
|
|
|
|
if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest;
|
|
memcpy(mode, i, sizeof(DisplayModeRec));
|
|
if(!((mode->Private = xalloc(sizeof(XGIMergedDisplayModeRec)))))
|
|
{
|
|
xfree(mode);
|
|
return dest;
|
|
}
|
|
((XGIMergedDisplayModePtr)mode->Private)->CRT1 = i;
|
|
((XGIMergedDisplayModePtr)mode->Private)->CRT2 = j;
|
|
((XGIMergedDisplayModePtr)mode->Private)->CRT2Position = srel;
|
|
mode->PrivSize = 0;
|
|
|
|
switch(srel)
|
|
{
|
|
case xgiLeftOf:
|
|
case xgiRightOf:
|
|
if(!(pScrn->display->virtualX))
|
|
{
|
|
dx = i->HDisplay + j->HDisplay;
|
|
}
|
|
else
|
|
{
|
|
dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay);
|
|
}
|
|
dx -= mode->HDisplay;
|
|
if(!(pScrn->display->virtualY))
|
|
{
|
|
dy = max(i->VDisplay, j->VDisplay);
|
|
}
|
|
else
|
|
{
|
|
dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay));
|
|
}
|
|
dy -= mode->VDisplay;
|
|
break;
|
|
case xgiAbove:
|
|
case xgiBelow:
|
|
if(!(pScrn->display->virtualY))
|
|
{
|
|
dy = i->VDisplay + j->VDisplay;
|
|
}
|
|
else
|
|
{
|
|
dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay);
|
|
}
|
|
dy -= mode->VDisplay;
|
|
if(!(pScrn->display->virtualX))
|
|
{
|
|
dx = max(i->HDisplay, j->HDisplay);
|
|
}
|
|
else
|
|
{
|
|
dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay));
|
|
}
|
|
dx -= mode->HDisplay;
|
|
break;
|
|
case xgiClone:
|
|
if(!(pScrn->display->virtualX))
|
|
{
|
|
dx = max(i->HDisplay, j->HDisplay);
|
|
}
|
|
else
|
|
{
|
|
dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay));
|
|
}
|
|
dx -= mode->HDisplay;
|
|
if(!(pScrn->display->virtualY))
|
|
{
|
|
dy = max(i->VDisplay, j->VDisplay);
|
|
}
|
|
else
|
|
{
|
|
dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay));
|
|
}
|
|
dy -= mode->VDisplay;
|
|
break;
|
|
}
|
|
mode->HDisplay += dx;
|
|
mode->HSyncStart += dx;
|
|
mode->HSyncEnd += dx;
|
|
mode->HTotal += dx;
|
|
mode->VDisplay += dy;
|
|
mode->VSyncStart += dy;
|
|
mode->VSyncEnd += dy;
|
|
mode->VTotal += dy;
|
|
mode->Clock = 0;
|
|
|
|
if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pXGI->maxxfbmem) ||
|
|
(mode->HDisplay > 4088) ||
|
|
(mode->VDisplay > 4096) )
|
|
{
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Skipped %dx%d, not enough video RAM or beyond hardware specs\n",
|
|
mode->HDisplay, mode->VDisplay);
|
|
xfree(mode->Private);
|
|
xfree(mode);
|
|
|
|
return dest;
|
|
}
|
|
|
|
#ifdef XGIXINERAMA
|
|
if(srel != xgiClone)
|
|
{
|
|
pXGI->AtLeastOneNonClone = TRUE;
|
|
}
|
|
#endif
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Merged %dx%d and %dx%d to %dx%d%s\n",
|
|
i->HDisplay, i->VDisplay, j->HDisplay, j->VDisplay,
|
|
mode->HDisplay, mode->VDisplay, (srel == xgiClone) ? " (Clone)" : "");
|
|
|
|
mode->next = mode;
|
|
mode->prev = mode;
|
|
|
|
if(dest)
|
|
{
|
|
mode->next = dest->next; /* Insert node after "dest" */
|
|
dest->next->prev = mode;
|
|
mode->prev = dest;
|
|
dest->next = mode;
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
/* Helper function to find a mode from a given name
|
|
* (Code base taken from mga driver)
|
|
*/
|
|
static DisplayModePtr
|
|
XGIGetModeFromName(char* str, DisplayModePtr i)
|
|
{
|
|
DisplayModePtr c = i;
|
|
if(!i) return NULL;
|
|
do
|
|
{
|
|
if(strcmp(str, c->name) == 0) return c;
|
|
c = c->next;
|
|
}
|
|
while(c != i);
|
|
return NULL;
|
|
}
|
|
|
|
static DisplayModePtr
|
|
XGIFindWidestTallestMode(DisplayModePtr i, Bool tallest)
|
|
{
|
|
DisplayModePtr c = i, d = NULL;
|
|
int max = 0;
|
|
if(!i) return NULL;
|
|
do
|
|
{
|
|
if(tallest)
|
|
{
|
|
if(c->VDisplay > max)
|
|
{
|
|
max = c->VDisplay;
|
|
d = c;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(c->HDisplay > max)
|
|
{
|
|
max = c->HDisplay;
|
|
d = c;
|
|
}
|
|
}
|
|
c = c->next;
|
|
}
|
|
while(c != i);
|
|
return d;
|
|
}
|
|
|
|
static DisplayModePtr
|
|
XGIGenerateModeListFromLargestModes(ScrnInfoPtr pScrn,
|
|
DisplayModePtr i, DisplayModePtr j,
|
|
XGIScrn2Rel srel)
|
|
{
|
|
#ifdef XGIXINERAMA
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
#endif
|
|
DisplayModePtr mode1 = NULL;
|
|
DisplayModePtr mode2 = NULL;
|
|
DisplayModePtr result = NULL;
|
|
|
|
#ifdef XGIXINERAMA
|
|
pXGI->AtLeastOneNonClone = FALSE;
|
|
#endif
|
|
|
|
switch(srel)
|
|
{
|
|
case xgiLeftOf:
|
|
case xgiRightOf:
|
|
mode1 = XGIFindWidestTallestMode(i, FALSE);
|
|
mode2 = XGIFindWidestTallestMode(j, FALSE);
|
|
break;
|
|
case xgiAbove:
|
|
case xgiBelow:
|
|
mode1 = XGIFindWidestTallestMode(i, TRUE);
|
|
mode2 = XGIFindWidestTallestMode(j, TRUE);
|
|
break;
|
|
case xgiClone:
|
|
mode1 = i;
|
|
mode2 = j;
|
|
}
|
|
|
|
if(mode1 && mode2)
|
|
{
|
|
return(XGICopyModeNLink(pScrn, result, mode1, mode2, srel));
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Generate the merged-fb mode modelist from metamodes
|
|
* (Code base taken from mga driver)
|
|
*/
|
|
static DisplayModePtr
|
|
XGIGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
|
|
DisplayModePtr i, DisplayModePtr j,
|
|
XGIScrn2Rel srel)
|
|
{
|
|
#ifdef XGIXINERAMA
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
#endif
|
|
char* strmode = str;
|
|
char modename[256];
|
|
Bool gotdash = FALSE;
|
|
XGIScrn2Rel sr;
|
|
DisplayModePtr mode1 = NULL;
|
|
DisplayModePtr mode2 = NULL;
|
|
DisplayModePtr result = NULL;
|
|
|
|
#ifdef XGIXINERAMA
|
|
pXGI->AtLeastOneNonClone = FALSE;
|
|
#endif
|
|
|
|
do
|
|
{
|
|
switch(*str)
|
|
{
|
|
case 0:
|
|
case '-':
|
|
case ' ':
|
|
if((strmode != str))
|
|
{
|
|
|
|
strncpy(modename, strmode, str - strmode);
|
|
modename[str - strmode] = 0;
|
|
|
|
if(gotdash)
|
|
{
|
|
if(mode1 == NULL) return NULL;
|
|
mode2 = XGIGetModeFromName(modename, j);
|
|
if(!mode2)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Mode \"%s\" is not a supported mode for CRT2\n", modename);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Skipping metamode \"%s-%s\".\n", mode1->name, modename);
|
|
mode1 = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mode1 = XGIGetModeFromName(modename, i);
|
|
if(!mode1)
|
|
{
|
|
char* tmps = str;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Mode \"%s\" is not a supported mode for CRT1\n", modename);
|
|
gotdash = FALSE;
|
|
while(*tmps == ' ') tmps++;
|
|
if(*tmps == '-')
|
|
{ /* skip the next mode */
|
|
tmps++;
|
|
while((*tmps == ' ') && (*tmps != 0)) tmps++; /* skip spaces */
|
|
while((*tmps != ' ') && (*tmps != '-') && (*tmps != 0)) tmps++; /* skip modename */
|
|
strncpy(modename,strmode,tmps - strmode);
|
|
modename[tmps - strmode] = 0;
|
|
str = tmps-1;
|
|
}
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Skipping metamode \"%s\".\n", modename);
|
|
mode1 = NULL;
|
|
}
|
|
}
|
|
gotdash = FALSE;
|
|
}
|
|
strmode = str + 1;
|
|
gotdash |= (*str == '-');
|
|
|
|
if(*str != 0) break;
|
|
/* Fall through otherwise */
|
|
|
|
default:
|
|
if(!gotdash && mode1)
|
|
{
|
|
sr = srel;
|
|
if(!mode2)
|
|
{
|
|
mode2 = XGIGetModeFromName(mode1->name, j);
|
|
sr = xgiClone;
|
|
}
|
|
if(!mode2)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Mode: \"%s\" is not a supported mode for CRT2\n", mode1->name);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Skipping metamode \"%s\".\n", modename);
|
|
mode1 = NULL;
|
|
}
|
|
else
|
|
{
|
|
result = XGICopyModeNLink(pScrn, result, mode1, mode2, sr);
|
|
mode1 = NULL;
|
|
mode2 = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
while(*(str++) != 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
static DisplayModePtr
|
|
XGIGenerateModeList(ScrnInfoPtr pScrn, char* str,
|
|
DisplayModePtr i, DisplayModePtr j,
|
|
XGIScrn2Rel srel)
|
|
{
|
|
if(str != NULL)
|
|
{
|
|
return(XGIGenerateModeListFromMetaModes(pScrn, str, i, j, srel));
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"No MetaModes given, linking %s modes by default\n",
|
|
(srel == xgiClone) ? "first" :
|
|
(((srel == xgiLeftOf) || (srel == xgiRightOf)) ? "widest" : "tallest"));
|
|
return(XGIGenerateModeListFromLargestModes(pScrn, i, j, srel));
|
|
}
|
|
}
|
|
|
|
static void
|
|
XGIRecalcDefaultVirtualSize(ScrnInfoPtr pScrn)
|
|
{
|
|
DisplayModePtr mode, bmode;
|
|
int max;
|
|
static const char *str = "MergedFB: Virtual %s %d\n";
|
|
|
|
if(!(pScrn->display->virtualX))
|
|
{
|
|
mode = bmode = pScrn->modes;
|
|
max = 0;
|
|
do
|
|
{
|
|
if(mode->HDisplay > max) max = mode->HDisplay;
|
|
mode = mode->next;
|
|
}
|
|
while(mode != bmode);
|
|
pScrn->virtualX = max;
|
|
pScrn->displayWidth = max;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", max);
|
|
}
|
|
if(!(pScrn->display->virtualY))
|
|
{
|
|
mode = bmode = pScrn->modes;
|
|
max = 0;
|
|
do
|
|
{
|
|
if(mode->VDisplay > max) max = mode->VDisplay;
|
|
mode = mode->next;
|
|
}
|
|
while(mode != bmode);
|
|
pScrn->virtualY = max;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", max);
|
|
}
|
|
}
|
|
|
|
static void
|
|
XGIMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, XGIScrn2Rel srel)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn1);
|
|
MessageType from = X_DEFAULT;
|
|
xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
|
|
xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
|
|
int ddcWidthmm = 0, ddcHeightmm = 0;
|
|
const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n";
|
|
|
|
/* This sets the DPI for MergedFB mode. The problem is that
|
|
* this can never be exact, because the output devices may
|
|
* have different dimensions. This function tries to compromise
|
|
* through a few assumptions, and it just calculates an average DPI
|
|
* value for both monitors.
|
|
*/
|
|
|
|
/* Given DisplaySize should regard BOTH monitors */
|
|
pScrn1->widthmm = pScrn1->monitor->widthmm;
|
|
pScrn1->heightmm = pScrn1->monitor->heightmm;
|
|
|
|
/* Get DDC display size; if only either CRT1 or CRT2 provided these,
|
|
* assume equal dimensions for both, otherwise add dimensions
|
|
*/
|
|
if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
|
|
(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) )
|
|
{
|
|
ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
|
|
ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
|
|
switch(srel)
|
|
{
|
|
case xgiLeftOf:
|
|
case xgiRightOf:
|
|
ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
|
|
break;
|
|
case xgiAbove:
|
|
case xgiBelow:
|
|
ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0))
|
|
{
|
|
ddcWidthmm = DDC1->features.hsize * 10;
|
|
ddcHeightmm = DDC1->features.vsize * 10;
|
|
switch(srel)
|
|
{
|
|
case xgiLeftOf:
|
|
case xgiRightOf:
|
|
ddcWidthmm *= 2;
|
|
break;
|
|
case xgiAbove:
|
|
case xgiBelow:
|
|
ddcHeightmm *= 2;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) )
|
|
{
|
|
ddcWidthmm = DDC2->features.hsize * 10;
|
|
ddcHeightmm = DDC2->features.vsize * 10;
|
|
switch(srel)
|
|
{
|
|
case xgiLeftOf:
|
|
case xgiRightOf:
|
|
ddcWidthmm *= 2;
|
|
break;
|
|
case xgiAbove:
|
|
case xgiBelow:
|
|
ddcHeightmm *= 2;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(monitorResolution > 0)
|
|
{
|
|
|
|
/* Set command line given values (overrules given options) */
|
|
pScrn1->xDpi = monitorResolution;
|
|
pScrn1->yDpi = monitorResolution;
|
|
from = X_CMDLINE;
|
|
|
|
}
|
|
else if(pXGI->MergedFBXDPI)
|
|
{
|
|
|
|
/* Set option-wise given values (overrule DisplaySize) */
|
|
pScrn1->xDpi = pXGI->MergedFBXDPI;
|
|
pScrn1->yDpi = pXGI->MergedFBYDPI;
|
|
from = X_CONFIG;
|
|
|
|
}
|
|
else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0)
|
|
{
|
|
|
|
/* Set values calculated from given DisplaySize */
|
|
from = X_CONFIG;
|
|
if(pScrn1->widthmm > 0)
|
|
{
|
|
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
|
|
}
|
|
if(pScrn1->heightmm > 0)
|
|
{
|
|
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
|
|
}
|
|
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
|
|
|
|
}
|
|
else if(ddcWidthmm && ddcHeightmm)
|
|
{
|
|
|
|
/* Set values from DDC-provided display size */
|
|
from = X_PROBED;
|
|
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm );
|
|
pScrn1->widthmm = ddcWidthmm;
|
|
pScrn1->heightmm = ddcHeightmm;
|
|
if(pScrn1->widthmm > 0)
|
|
{
|
|
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
|
|
}
|
|
if(pScrn1->heightmm > 0)
|
|
{
|
|
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
|
|
|
|
}
|
|
|
|
/* Sanity check */
|
|
if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0)
|
|
pScrn1->yDpi = pScrn1->xDpi;
|
|
if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0)
|
|
pScrn1->xDpi = pScrn1->yDpi;
|
|
|
|
pScrn2->xDpi = pScrn1->xDpi;
|
|
pScrn2->yDpi = pScrn1->yDpi;
|
|
|
|
xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
|
|
pScrn1->xDpi, pScrn1->yDpi);
|
|
}
|
|
|
|
static void
|
|
XGIFreeCRT2Structs(XGIPtr pXGI)
|
|
{
|
|
if(pXGI->CRT2pScrn)
|
|
{
|
|
if(pXGI->CRT2pScrn->modes)
|
|
{
|
|
while(pXGI->CRT2pScrn->modes)
|
|
xf86DeleteMode(&pXGI->CRT2pScrn->modes, pXGI->CRT2pScrn->modes);
|
|
}
|
|
if(pXGI->CRT2pScrn->monitor)
|
|
{
|
|
if(pXGI->CRT2pScrn->monitor->Modes)
|
|
{
|
|
while(pXGI->CRT2pScrn->monitor->Modes)
|
|
xf86DeleteMode(&pXGI->CRT2pScrn->monitor->Modes, pXGI->CRT2pScrn->monitor->Modes);
|
|
}
|
|
if(pXGI->CRT2pScrn->monitor->DDC) xfree(pXGI->CRT2pScrn->monitor->DDC);
|
|
xfree(pXGI->CRT2pScrn->monitor);
|
|
}
|
|
xfree(pXGI->CRT2pScrn);
|
|
pXGI->CRT2pScrn = NULL;
|
|
}
|
|
}
|
|
|
|
#endif /* End of MergedFB helpers */
|
|
|
|
static xf86MonPtr
|
|
XGIInternalDDC(ScrnInfoPtr pScrn, int crtno)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned char buffer[256];
|
|
|
|
int RealOff ;
|
|
unsigned char *page ;
|
|
|
|
xf86MonPtr pMonitor = NULL;
|
|
xf86Int10InfoPtr pInt = NULL ; /* Our int10 */
|
|
|
|
static char *crtno_means_str [] =
|
|
{
|
|
"CRT1","DVI","CRT2"
|
|
} ;
|
|
|
|
if( crtno > 2 || crtno < 0 )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIInternalDDC(): Can not get EDID for crtno = %d,abort.\n",crtno );
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGIInternalDDC(): getting EDID for %s.\n",crtno_means_str[crtno] );
|
|
}
|
|
|
|
if(xf86LoadSubModule(pScrn, "int10"))
|
|
{
|
|
xf86LoaderReqSymLists(int10Symbols, NULL);
|
|
pInt = xf86InitInt10(pXGI->pEnt->index);
|
|
if( pInt == NULL )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIInternalDDC(): Can not initialize pInt, abort.\n" );
|
|
return NULL ;
|
|
}
|
|
|
|
page = xf86Int10AllocPages(pInt,1,&RealOff);
|
|
if( page == NULL )
|
|
{
|
|
xf86FreeInt10(pInt) ;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIInternalDDC(): Can not initialize real mode buffer, abort.\n" );
|
|
return NULL ;
|
|
}
|
|
}
|
|
|
|
if( pInt )
|
|
{
|
|
pInt->ax = 0x4f15 ; /* VESA DDC supporting */
|
|
pInt->bx = 1 ; /* get EDID */
|
|
pInt->cx = crtno ; /* port 0 or 1 for CRT 1 or 2 */
|
|
pInt->es = SEG_ADDR(RealOff) ;
|
|
pInt->di = SEG_OFF(RealOff) ;
|
|
pInt->num = 0x10 ;
|
|
xf86ExecX86int10(pInt) ;
|
|
|
|
PDEBUG3(ErrorF("ax = %04X bx = %04X cx = %04X dx = %04X si = %04X di = %04X es = %04X\n",
|
|
pInt->ax, pInt->bx, pInt->cx, pInt->dx, pInt->si, pInt->di, pInt->es)) ;
|
|
|
|
if( (pInt->ax & 0xff00) == 0 )
|
|
{
|
|
int i,j ;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGIInternalDDC(): VESA get DDC success for CRT %d.\n",crtno+1 );
|
|
|
|
for( i = 0 ; i < 128 ; i++ )
|
|
{
|
|
buffer[i] = page[i] ;
|
|
}
|
|
|
|
#ifdef DEBUG5
|
|
for( i = 0 ; i < 128 ; i+=16)
|
|
{
|
|
ErrorF("EDID[%02X]",i);
|
|
for( j = 0 ; j < 16 ; j++)
|
|
{
|
|
ErrorF(" %02X",buffer[i+j]) ;
|
|
}
|
|
ErrorF("\n");
|
|
}
|
|
#endif /* DEBUG3 */
|
|
|
|
xf86LoaderReqSymLists(ddcSymbols, NULL);
|
|
pMonitor = xf86InterpretEDID(pScrn->scrnIndex, buffer) ;
|
|
|
|
if( pMonitor == NULL )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"CRT%d DDC EDID corrupt\n", crtno + 1);
|
|
return(NULL);
|
|
}
|
|
xf86UnloadSubModule("ddc");
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIInternalDDC(): VESA get DDC fail for CRT %d.\n",crtno+1 );
|
|
}
|
|
|
|
xf86Int10FreePages(pInt, page, 1);
|
|
xf86FreeInt10(pInt) ;
|
|
}
|
|
return pMonitor ;
|
|
}
|
|
|
|
/* static xf86MonPtr
|
|
XGIDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->SecondHead)
|
|
{
|
|
*crtnum = 1;
|
|
return(XGIInternalDDC(pScrn, 0));
|
|
}
|
|
else
|
|
{
|
|
*crtnum = 2;
|
|
return(XGIInternalDDC(pScrn, 1));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if(pXGI->CRT1off)
|
|
{
|
|
*crtnum = 2;
|
|
return(XGIInternalDDC(pScrn, 1));
|
|
}
|
|
else
|
|
{
|
|
*crtnum = 1;
|
|
return(XGIInternalDDC(pScrn, 0));
|
|
}
|
|
} */
|
|
|
|
|
|
static void
|
|
XGIDumpMonitorInfo(xf86MonPtr pMonitor)
|
|
{
|
|
#ifdef DEBUG5
|
|
struct detailed_timings *pd_timings;
|
|
Uchar *pserial;
|
|
Uchar *pascii_data;
|
|
Uchar *pname;
|
|
struct monitor_ranges *pranges;
|
|
struct std_timings *pstd_t;
|
|
struct whitePoints *pwp;
|
|
int i,j ;
|
|
|
|
if( pMonitor == NULL )
|
|
{
|
|
ErrorF("Monitor is NULL") ;
|
|
return ;
|
|
}
|
|
|
|
ErrorF("pMonitor->scrnIndex = %d\n",pMonitor->scrnIndex);
|
|
ErrorF("vendor = %c%c%c%c, prod_id = %x serial = %d week = %d year = %d\n",
|
|
pMonitor->vendor.name[0], pMonitor->vendor.name[1],
|
|
pMonitor->vendor.name[2], pMonitor->vendor.name[3],
|
|
pMonitor->vendor.prod_id,
|
|
pMonitor->vendor.serial,
|
|
pMonitor->vendor.week,
|
|
pMonitor->vendor.year) ;
|
|
|
|
ErrorF("ver = %d %d\n",
|
|
pMonitor->ver.version,
|
|
pMonitor->ver.revision) ;
|
|
ErrorF("intput type = %d voltage = %d setup = %d sync = %d\n",
|
|
pMonitor->features.input_type,
|
|
pMonitor->features.input_voltage,
|
|
pMonitor->features.input_setup,
|
|
pMonitor->features.input_sync ) ;
|
|
ErrorF("hsize = %d vsize = %d gamma=%8.3f\n",
|
|
pMonitor->features.hsize,
|
|
pMonitor->features.vsize,
|
|
pMonitor->features.gamma) ;
|
|
|
|
ErrorF("dpms = %d display_type = %d msc = %d\n",
|
|
pMonitor->features.dpms,
|
|
pMonitor->features.display_type,
|
|
pMonitor->features.msc ) ;
|
|
ErrorF("redx,redy,greenx,greeny,bluex,bluey,whitex,whitey = %8.3f,%8.3f,%8.3f,%8.3f,%8.3f,%8.3f,%8.3f,%8.3f\n",
|
|
pMonitor->features.redx,
|
|
pMonitor->features.redy,
|
|
pMonitor->features.greenx,
|
|
pMonitor->features.greeny,
|
|
pMonitor->features.bluex,
|
|
pMonitor->features.bluey,
|
|
pMonitor->features.whitex,
|
|
pMonitor->features.whitey ) ;
|
|
|
|
ErrorF("established_timings = (t1)%d%d%d%d%d%d%d%d",
|
|
(pMonitor->timings1.t1>>7)&1,
|
|
(pMonitor->timings1.t1>>6)&1,
|
|
(pMonitor->timings1.t1>>5)&1,
|
|
(pMonitor->timings1.t1>>4)&1,
|
|
(pMonitor->timings1.t1>>3)&1,
|
|
(pMonitor->timings1.t1>>2)&1,
|
|
(pMonitor->timings1.t1>>1)&1,
|
|
(pMonitor->timings1.t1>>0)&1);
|
|
ErrorF("(t2) %d%d%d%d%d%d%d%d",
|
|
(pMonitor->timings1.t1>>7)&1,
|
|
(pMonitor->timings1.t1>>6)&1,
|
|
(pMonitor->timings1.t1>>5)&1,
|
|
(pMonitor->timings1.t1>>4)&1,
|
|
(pMonitor->timings1.t1>>3)&1,
|
|
(pMonitor->timings1.t1>>2)&1,
|
|
(pMonitor->timings1.t1>>1)&1,
|
|
(pMonitor->timings1.t1>>0)&1);
|
|
ErrorF("(t_manu)%d%d%d%d%d%d%d%d\n",
|
|
(pMonitor->timings1.t_manu>>7)&1,
|
|
(pMonitor->timings1.t_manu>>6)&1,
|
|
(pMonitor->timings1.t_manu>>5)&1,
|
|
(pMonitor->timings1.t_manu>>4)&1,
|
|
(pMonitor->timings1.t_manu>>3)&1,
|
|
(pMonitor->timings1.t_manu>>2)&1,
|
|
(pMonitor->timings1.t_manu>>1)&1,
|
|
(pMonitor->timings1.t_manu>>0)&1);
|
|
|
|
for( i = 0 ; i < 7 ; i++ )
|
|
{
|
|
ErrorF("std timing %d: hsize = %d, vsize = %d, refresh = %d, id = %d\n",
|
|
i,
|
|
pMonitor->timings2[i].hsize,
|
|
pMonitor->timings2[i].vsize,
|
|
pMonitor->timings2[i].refresh,
|
|
pMonitor->timings2[i].id ) ;
|
|
}
|
|
|
|
for( i = 0 ; i < 4 ; i++ )
|
|
{
|
|
ErrorF("Detail timing section %d\n",i ) ;
|
|
ErrorF("type = %x\n",pMonitor->det_mon[i].type ) ;
|
|
switch( pMonitor->det_mon[i].type )
|
|
{
|
|
case DS_SERIAL:
|
|
ErrorF("type = %x DS_SERIAL = %x\n",pMonitor->det_mon[i].type,DS_SERIAL) ;
|
|
break ;
|
|
case DS_ASCII_STR:
|
|
ErrorF("type = %x DS_ASCII_STR = %x\n",pMonitor->det_mon[i].type,DS_ASCII_STR) ;
|
|
break ;
|
|
case DS_NAME:
|
|
ErrorF("type = %x DS_NAME = %x\n",pMonitor->det_mon[i].type,DS_NAME) ;
|
|
break ;
|
|
case DS_RANGES:
|
|
ErrorF("type = %x DS_RANGES = %x\n",pMonitor->det_mon[i].type,DS_RANGES) ;
|
|
break ;
|
|
case DS_WHITE_P:
|
|
ErrorF("type = %x DS_WHITE_P = %x\n",pMonitor->det_mon[i].type,DS_WHITE_P) ;
|
|
break ;
|
|
case DS_STD_TIMINGS:
|
|
ErrorF("type = %x DS_STD_TIMINGS = %x\n",pMonitor->det_mon[i].type,DS_STD_TIMINGS) ;
|
|
break ;
|
|
}
|
|
switch( pMonitor->det_mon[i].type )
|
|
{
|
|
case DS_SERIAL:
|
|
pserial = pMonitor->det_mon[i].section.serial ;
|
|
ErrorF("seial: ") ;
|
|
for( j = 0 ; j < 13 ; j++ )
|
|
{
|
|
ErrorF("%02X",pserial[j]) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
break ;
|
|
case DS_ASCII_STR:
|
|
pascii_data = pMonitor->det_mon[i].section.ascii_data ;
|
|
ErrorF("ascii: ") ;
|
|
for( j = 0 ; j < 13 ; j++ )
|
|
{
|
|
ErrorF("%c",pascii_data[j]) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
break ;
|
|
case DS_NAME:
|
|
pname = pMonitor->det_mon[i].section.name ;
|
|
ErrorF("name: ") ;
|
|
for( j = 0 ; j < 13 ; j++ )
|
|
{
|
|
ErrorF("%c",pname[j]) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
break ;
|
|
case DS_RANGES:
|
|
pranges = &(pMonitor->det_mon[i].section.ranges) ;
|
|
ErrorF("min_v = %d max_v = %d min_h = %d max_h = %d max_clock = %d\n",
|
|
pranges->min_v,pranges->max_v,
|
|
pranges->min_h,pranges->max_h,
|
|
pranges->max_clock) ;
|
|
break ;
|
|
case DS_WHITE_P:
|
|
pwp = pMonitor->det_mon[i].section.wp ;
|
|
for( j = 0 ; j < 2 ; j++ )
|
|
{
|
|
ErrorF("wp[%d].index = %d white_x = %8.3f white_y = %8.3f white_gamma = %8.3f\n",
|
|
j,pwp[j].index,pwp[j].white_x,pwp[j].white_y,pwp[j].white_gamma) ;
|
|
}
|
|
break ;
|
|
case DS_STD_TIMINGS:
|
|
pstd_t = pMonitor->det_mon[i].section.std_t ;
|
|
for(j = 0 ; j < 5 ; j++ )
|
|
{
|
|
ErrorF("std_t[%d] hsize = %d vsize = %d refresh = %d id = %d\n",
|
|
j,pstd_t[j].hsize,pstd_t[j].vsize,pstd_t[j].refresh,pstd_t[j].id ) ;
|
|
}
|
|
break ;
|
|
case DT:
|
|
|
|
pd_timings = &pMonitor->det_mon[i].section.d_timings ;
|
|
ErrorF("Detail Timing Descriptor\n" );
|
|
ErrorF("clock = %d\n",pd_timings->clock );
|
|
ErrorF("h_active = %d\n",pd_timings->h_active );
|
|
ErrorF("h_blanking = %d\n",pd_timings->h_blanking );
|
|
ErrorF("v_active = %d\n",pd_timings->v_active );
|
|
ErrorF("v_blanking = %d\n",pd_timings->v_blanking );
|
|
ErrorF("h_sync_off = %d\n",pd_timings->h_sync_off );
|
|
ErrorF("h_sync_width = %d\n",pd_timings->h_sync_width );
|
|
ErrorF("v_sync_off = %d\n",pd_timings->v_sync_off );
|
|
ErrorF("v_sync_width = %d\n",pd_timings->v_sync_width );
|
|
ErrorF("h_size = %d\n",pd_timings->h_size );
|
|
ErrorF("v_size = %d\n",pd_timings->v_size );
|
|
ErrorF("h_border = %d\n",pd_timings->h_border );
|
|
ErrorF("v_border = %d\n",pd_timings->v_border );
|
|
ErrorF("interlaced = %d stereo = %x sync = %x misc = %x\n",
|
|
pd_timings->interlaced,
|
|
pd_timings->stereo,
|
|
pd_timings->sync,
|
|
pd_timings->misc);
|
|
break ;
|
|
}
|
|
}
|
|
|
|
for( i = 0 ;i < 128 ; i+=16 )
|
|
{
|
|
ErrorF("rawData[%02X]:",i) ;
|
|
for( j = 0 ; j < 16 ; j++ )
|
|
{
|
|
ErrorF(" %02X",pMonitor->rawData[i+j]) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
XGIGetMonitorRangeByDDC(MonitorRangePtr range, xf86MonPtr pMonitor)
|
|
{
|
|
int i,j ;
|
|
float VF,HF ;
|
|
struct detailed_timings *pd_timings;
|
|
struct monitor_ranges *pranges;
|
|
struct std_timings *pstd_t;
|
|
|
|
if((range == NULL)||(pMonitor == NULL))
|
|
{
|
|
return ; /* ignore */
|
|
}
|
|
|
|
PDEBUG5(ErrorF("establish timing t1 = %02x t2=%02x\n",pMonitor->timings1.t1,pMonitor->timings1.t2));
|
|
for( i = 0,j=0 ; i < 8 ; i++ ,j++)
|
|
{
|
|
if( establish_timing[j].width == -1 )
|
|
{
|
|
continue ;
|
|
}
|
|
|
|
if(pMonitor->timings1.t1 & (1<<i))
|
|
{
|
|
PDEBUG5(ErrorF("Support %dx%d@%4.1fHz Hseq = %8.3fKHz\n",
|
|
establish_timing[j].width,
|
|
establish_timing[j].height,
|
|
establish_timing[j].VRefresh,
|
|
establish_timing[j].HSync)) ;
|
|
|
|
if(range->loH > establish_timing[j].HSync)
|
|
{
|
|
range->loH = establish_timing[j].HSync ;
|
|
}
|
|
|
|
if(range->hiH < establish_timing[j].HSync)
|
|
{
|
|
range->hiH = establish_timing[j].HSync ;
|
|
}
|
|
|
|
if(range->loV > establish_timing[j].VRefresh)
|
|
{
|
|
range->loV = establish_timing[j].VRefresh ;
|
|
}
|
|
|
|
if(range->hiV < establish_timing[j].VRefresh)
|
|
{
|
|
range->hiV = establish_timing[j].VRefresh ;
|
|
}
|
|
}
|
|
}
|
|
PDEBUG5(ErrorF("check establish timing t1:range ( %8.3f %8.3f %8.3f %8.3f )\n",
|
|
range->loH,range->loV,range->hiH,range->hiV )) ;
|
|
|
|
for( i = 0 ; i < 8 ; i++ ,j++)
|
|
{
|
|
if( establish_timing[j].width == -1 )
|
|
{
|
|
continue ;
|
|
}
|
|
|
|
if(pMonitor->timings1.t2 & (1<<i))
|
|
{
|
|
PDEBUG5(ErrorF("Support %dx%d@%4.1fHz Hseq = %8.3fKHz\n",
|
|
establish_timing[j].width,
|
|
establish_timing[j].height,
|
|
establish_timing[j].VRefresh,
|
|
establish_timing[j].HSync)) ;
|
|
|
|
if(range->loH > establish_timing[j].HSync)
|
|
{
|
|
range->loH = establish_timing[j].HSync ;
|
|
}
|
|
|
|
if(range->hiH < establish_timing[j].HSync)
|
|
{
|
|
range->hiH = establish_timing[j].HSync ;
|
|
}
|
|
|
|
if(range->loV > establish_timing[j].VRefresh)
|
|
{
|
|
range->loV = establish_timing[j].VRefresh ;
|
|
}
|
|
|
|
if(range->hiV < establish_timing[j].VRefresh)
|
|
{
|
|
range->hiV = establish_timing[j].VRefresh ;
|
|
}
|
|
}
|
|
}
|
|
PDEBUG5(ErrorF("check establish timing t2:range ( %8.3f %8.3f %8.3f %8.3f )\n",
|
|
range->loH,range->loV,range->hiH,range->hiV)) ;
|
|
|
|
for( i = 0 ; i < 8 ; i++ )
|
|
{
|
|
for( j = 0 ; StdTiming[j].width != -1 ; j++ )
|
|
{
|
|
if ((StdTiming[j].width == pMonitor->timings2[i].hsize)&&
|
|
(StdTiming[j].height == pMonitor->timings2[i].vsize)&&
|
|
(StdTiming[j].VRefresh == pMonitor->timings2[i].refresh))
|
|
{
|
|
PDEBUG5(ErrorF("pMonitor->timings2[%d]= %d %d %d %d\n",
|
|
i,
|
|
pMonitor->timings2[i].hsize,
|
|
pMonitor->timings2[i].vsize,
|
|
pMonitor->timings2[i].refresh,
|
|
pMonitor->timings2[i].id)) ;
|
|
HF = StdTiming[j].HSync ;
|
|
VF = StdTiming[j].VRefresh ;
|
|
if( range->loH > HF ) range->loH = HF ;
|
|
if( range->loV > VF ) range->loV = VF ;
|
|
if( range->hiH < HF ) range->hiH = HF ;
|
|
if( range->hiV < VF ) range->hiV = VF ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
PDEBUG5(ErrorF("check standard timing :range ( %8.3f %8.3f %8.3f %8.3f )\n",
|
|
range->loH,range->loV,range->hiH,range->hiV )) ;
|
|
|
|
for( i = 0 ; i < 4 ; i++ )
|
|
{
|
|
switch( pMonitor->det_mon[i].type )
|
|
{
|
|
case DS_RANGES:
|
|
pranges = &(pMonitor->det_mon[i].section.ranges) ;
|
|
PDEBUG5(ErrorF("min_v = %d max_v = %d min_h = %d max_h = %d max_clock = %d\n",
|
|
pranges->min_v,pranges->max_v,
|
|
pranges->min_h,pranges->max_h,
|
|
pranges->max_clock)) ;
|
|
|
|
if( range->loH > pranges->min_h) range->loH = pranges->min_h ;
|
|
if( range->loV > pranges->min_v) range->loV = pranges->min_v ;
|
|
if( range->hiH < pranges->max_h) range->hiH = pranges->max_h ;
|
|
if( range->hiV < pranges->max_v) range->hiV = pranges->max_v ;
|
|
PDEBUG5(ErrorF("range(%8.3f %8.3f %8.3f %8.3f)\n",range->loH,range->loV,range->hiH,range->hiV)) ;
|
|
break ;
|
|
|
|
case DS_STD_TIMINGS:
|
|
pstd_t = pMonitor->det_mon[i].section.std_t ;
|
|
for(j = 0 ; j < 5 ; j++ )
|
|
{
|
|
int k ;
|
|
PDEBUG5(ErrorF("std_t[%d] hsize = %d vsize = %d refresh = %d id = %d\n",
|
|
j,pstd_t[j].hsize,pstd_t[j].vsize,pstd_t[j].refresh,pstd_t[j].id) ) ;
|
|
for( k = 0 ; StdTiming[k].width != -1 ; k++ )
|
|
{
|
|
if((StdTiming[k].width == pstd_t[j].hsize)&&
|
|
(StdTiming[k].height == pstd_t[j].vsize)&&
|
|
(StdTiming[k].VRefresh == pstd_t[j].refresh))
|
|
{
|
|
if(range->loH > StdTiming[k].HSync) range->loH = StdTiming[k].HSync ;
|
|
if(range->hiH < StdTiming[k].HSync) range->hiH = StdTiming[k].HSync ;
|
|
if(range->loV > StdTiming[k].VRefresh) range->loV = StdTiming[k].VRefresh ;
|
|
if(range->hiV < StdTiming[k].VRefresh) range->hiV = StdTiming[k].VRefresh ;
|
|
break ;
|
|
}
|
|
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case DT:
|
|
|
|
pd_timings = &pMonitor->det_mon[i].section.d_timings ;
|
|
|
|
HF = pd_timings->clock / (pd_timings->h_active+pd_timings->h_blanking) ;
|
|
VF = HF / (pd_timings->v_active+pd_timings->v_blanking) ;
|
|
HF /= 1000 ; /* into KHz Domain */
|
|
if( range->loH > HF ) range->loH = HF ;
|
|
if( range->hiH < HF ) range->hiH = HF ;
|
|
if( range->loV > VF ) range->loV = VF ;
|
|
if( range->hiV < VF ) range->hiV = VF ;
|
|
PDEBUG(ErrorF("Detailing Timing: HF = %f VF = %f range (%8.3f %8.3f %8.3f %8.3f)\n",HF,VF,range->loH,range->loV,range->hiH,range->hiV)) ;
|
|
break ;
|
|
}
|
|
}
|
|
PDEBUG5(ErrorF("Done range(%8.3f %8.3f %8.3f %8.3f)\n",range->loH,range->loV,range->hiH,range->hiV)) ;
|
|
|
|
}
|
|
|
|
static void
|
|
XGISyncDDCMonitorRange(MonPtr monitor, MonitorRangePtr range)
|
|
{
|
|
int i ;
|
|
if( (monitor == NULL) || (range == NULL))
|
|
{
|
|
return ;
|
|
}
|
|
|
|
for( i = 0 ; i < monitor->nHsync ; i++ )
|
|
{
|
|
monitor->hsync[i].lo = range->loH ;
|
|
monitor->hsync[i].hi = range->hiH ;
|
|
}
|
|
|
|
for( i = 0 ; i < monitor->nVrefresh ; i++ )
|
|
{
|
|
monitor->vrefresh[i].lo = range->loV ;
|
|
monitor->vrefresh[i].hi = range->hiV ;
|
|
}
|
|
}
|
|
|
|
static void
|
|
XGIDDCPreInit(ScrnInfoPtr pScrn)
|
|
{
|
|
|
|
XGIPtr pXGI=XGIPTR(pScrn);
|
|
xf86MonPtr pMonitor = NULL;
|
|
xf86MonPtr pMonitorDVI = NULL;
|
|
Bool didddc2;
|
|
|
|
static const char *ddcsstr = "CRT%d DDC monitor info: ************************************\n";
|
|
static const char *ddcestr = "End of CRT%d DDC monitor info ******************************\n";
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,14,0)
|
|
static const char *subshstr = "Substituting missing CRT%d monitor HSync data by DDC data\n";
|
|
static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh data by DDC data\n";
|
|
#endif
|
|
|
|
/* Now for something completely different: DDC.
|
|
* For 300 and 315/330 series, we provide our
|
|
* own functions (in order to probe CRT2 as well)
|
|
* If these fail, use the VBE.
|
|
* All other chipsets will use VBE. No need to re-invent
|
|
* the wheel there.
|
|
*/
|
|
|
|
pXGI->pVbe = NULL;
|
|
didddc2 = FALSE;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* In dual head mode, probe DDC using VBE only for CRT1 (second head) */
|
|
if((pXGI->DualHeadMode) && (!didddc2) && (!pXGI->SecondHead))
|
|
didddc2 = TRUE;
|
|
#endif
|
|
|
|
if(!didddc2)
|
|
{
|
|
/* If CRT1 is off or LCDA, skip DDC via VBE */
|
|
if((pXGI->CRT1off) || (pXGI->VBFlags & CRT1_LCDA))
|
|
didddc2 = TRUE;
|
|
}
|
|
|
|
/* Now (re-)load and initialize the DDC module */
|
|
if(!didddc2)
|
|
{
|
|
|
|
if(xf86LoadSubModule(pScrn, "ddc"))
|
|
{
|
|
|
|
xf86LoaderReqSymLists(ddcSymbols, NULL);
|
|
|
|
pMonitor = XGIInternalDDC(pScrn,0) ;
|
|
if(pMonitor == NULL )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Could not retrieve DDC data\n");
|
|
}
|
|
|
|
if( pXGI->xgi_HwDevExt.jChipType == XG21 )
|
|
{
|
|
PDEBUG(ErrorF("Getting XG21 DVI EDID...\n")) ;
|
|
pMonitorDVI = XGIInternalDDC(pScrn,1) ;
|
|
if( pMonitorDVI == NULL )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Could not retrieve DVI DDC data\n");
|
|
}
|
|
|
|
if( (pMonitor == NULL) && (pMonitorDVI != NULL))
|
|
{
|
|
pMonitor = pMonitorDVI ;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/* initialize */
|
|
|
|
if( pMonitor )
|
|
{
|
|
pXGI->CRT1Range.loH = 1000 ;
|
|
pXGI->CRT1Range.loV = 1000 ;
|
|
pXGI->CRT1Range.hiH = 0 ;
|
|
pXGI->CRT1Range.hiV = 0 ;
|
|
XGIGetMonitorRangeByDDC(&(pXGI->CRT1Range), pMonitor) ;
|
|
}
|
|
else
|
|
{
|
|
pXGI->CRT1Range.loH = 0 ;
|
|
pXGI->CRT1Range.loV = 0 ;
|
|
pXGI->CRT1Range.hiH = 1000 ;
|
|
pXGI->CRT1Range.hiV = 1000 ;
|
|
}
|
|
|
|
if( pMonitorDVI )
|
|
{
|
|
pXGI->CRT2Range.loV = 1000 ;
|
|
pXGI->CRT2Range.loH = 1000 ;
|
|
pXGI->CRT2Range.hiH = 0 ;
|
|
pXGI->CRT2Range.hiV = 0 ;
|
|
XGIGetMonitorRangeByDDC(&(pXGI->CRT2Range), pMonitorDVI) ;
|
|
}
|
|
else
|
|
{
|
|
pXGI->CRT2Range.loH = 0 ;
|
|
pXGI->CRT2Range.loV = 0 ;
|
|
pXGI->CRT2Range.hiH = 1000 ;
|
|
pXGI->CRT2Range.hiV = 1000 ;
|
|
}
|
|
|
|
if( pXGI->xgi_HwDevExt.jChipType == XG21 )
|
|
{
|
|
/* Mode range intersecting */
|
|
if( pXGI->CRT1Range.loH < pXGI->CRT2Range.loH )
|
|
{
|
|
pXGI->CRT1Range.loH = pXGI->CRT2Range.loH ;
|
|
}
|
|
if( pXGI->CRT1Range.loV < pXGI->CRT2Range.loV )
|
|
{
|
|
pXGI->CRT1Range.loV = pXGI->CRT2Range.loV ;
|
|
}
|
|
if( pXGI->CRT1Range.hiH > pXGI->CRT2Range.hiH )
|
|
{
|
|
pXGI->CRT1Range.hiH = pXGI->CRT2Range.hiH ;
|
|
}
|
|
if( pXGI->CRT1Range.hiV > pXGI->CRT2Range.hiV )
|
|
{
|
|
pXGI->CRT1Range.hiV = pXGI->CRT2Range.hiV ;
|
|
}
|
|
}
|
|
|
|
if( pMonitor )
|
|
{
|
|
XGISyncDDCMonitorRange(pScrn->monitor,&pXGI->CRT1Range) ;
|
|
}
|
|
|
|
if(pScrn->monitor)
|
|
{
|
|
pScrn->monitor->DDC = pMonitor ;
|
|
}
|
|
|
|
return ;
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
pXGI->CRT2pScrn->monitor = xalloc(sizeof(MonRec));
|
|
if(pXGI->CRT2pScrn->monitor)
|
|
{
|
|
DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL;
|
|
memcpy(pXGI->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec));
|
|
pXGI->CRT2pScrn->monitor->DDC = NULL;
|
|
pXGI->CRT2pScrn->monitor->Modes = NULL;
|
|
tempm = pScrn->monitor->Modes;
|
|
while(tempm)
|
|
{
|
|
if(!(newm = xalloc(sizeof(DisplayModeRec)))) break;
|
|
memcpy(newm, tempm, sizeof(DisplayModeRec));
|
|
if(!(newm->name = xalloc(strlen(tempm->name) + 1)))
|
|
{
|
|
xfree(newm);
|
|
break;
|
|
}
|
|
strcpy(newm->name, tempm->name);
|
|
if(!pXGI->CRT2pScrn->monitor->Modes) pXGI->CRT2pScrn->monitor->Modes = newm;
|
|
if(currentm)
|
|
{
|
|
currentm->next = newm;
|
|
newm->prev = currentm;
|
|
}
|
|
currentm = newm;
|
|
tempm = tempm->next;
|
|
}
|
|
|
|
if((pMonitor = XGIInternalDDC(pXGI->CRT2pScrn, 1)))
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2);
|
|
xf86PrintEDID(pMonitor);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2);
|
|
xf86SetDDCproperties(pXGI->CRT2pScrn, pMonitor);
|
|
|
|
pXGI->CRT2pScrn->monitor->DDC = pMonitor;
|
|
|
|
/* use DDC data if no ranges in config file */
|
|
if(!pXGI->CRT2HSync)
|
|
{
|
|
pXGI->CRT2pScrn->monitor->nHsync = 0;
|
|
}
|
|
if(!pXGI->CRT2VRefresh)
|
|
{
|
|
pXGI->CRT2pScrn->monitor->nVrefresh = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Failed to read DDC data for CRT2\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XGIErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n",
|
|
mergeddisstr);
|
|
if(pXGI->CRT2pScrn) xfree(pXGI->CRT2pScrn);
|
|
pXGI->CRT2pScrn = NULL;
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* If there is no HSync or VRefresh data for the monitor,
|
|
* derive it from DDC data. Done by common layer since
|
|
* 4.3.99.14.
|
|
*/
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,14,0)
|
|
if(pScrn->monitor->DDC)
|
|
{
|
|
if(pScrn->monitor->nHsync <= 0)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr,
|
|
#ifdef XGIDUALHEAD
|
|
pXGI->DualHeadMode ? (pXGI->SecondHead ? 1 : 2) :
|
|
#endif
|
|
pXGI->CRT1off ? 2 : 1);
|
|
XGISetSyncRangeFromEdid(pScrn, 1);
|
|
}
|
|
|
|
if(pScrn->monitor->nVrefresh <= 0)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr,
|
|
#ifdef XGIDUALHEAD
|
|
pXGI->DualHeadMode ? (pXGI->SecondHead ? 1 : 2) :
|
|
#endif
|
|
pXGI->CRT1off ? 2 : 1);
|
|
XGISetSyncRangeFromEdid(pScrn, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,14,0)
|
|
if(pXGI->CRT2pScrn->monitor->DDC)
|
|
{
|
|
if(pXGI->CRT2pScrn->monitor->nHsync <= 0)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2);
|
|
XGISetSyncRangeFromEdid(pXGI->CRT2pScrn, 1);
|
|
}
|
|
if(pXGI->CRT2pScrn->monitor->nVrefresh <= 0)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2);
|
|
XGISetSyncRangeFromEdid(pXGI->CRT2pScrn, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1);
|
|
}
|
|
#endif
|
|
|
|
/* end of DDC */
|
|
}
|
|
|
|
static void
|
|
XGIDumpModePtr(DisplayModePtr mode)
|
|
{
|
|
#ifdef DEBUG5
|
|
if(mode == NULL) return ;
|
|
|
|
ErrorF("Dump DisplayModePtr mode\n") ;
|
|
ErrorF("name = %s\n",mode->name);
|
|
/* ModeStatus status; */
|
|
ErrorF("type = %d\n",mode->type) ;
|
|
ErrorF("Clock = %d\n",mode->Clock) ;
|
|
ErrorF("HDisplay = %d\n",mode->HDisplay) ;
|
|
ErrorF("HSyncStart = %d\n",mode->HSyncStart) ;
|
|
ErrorF("HSyncEnd = %d\n",mode->HSyncEnd) ;
|
|
ErrorF("HTotal = %d\n",mode->HTotal) ;
|
|
ErrorF("HSkew = %d\n",mode->HSkew) ;
|
|
ErrorF("VDisplay = %d\n",mode->VDisplay) ;
|
|
ErrorF("VSyncStart = %d\n",mode->VSyncStart) ;
|
|
ErrorF("VSyncEnd = %d\n",mode->VSyncEnd) ;
|
|
ErrorF("VTotal = %d\n",mode->VTotal) ;
|
|
ErrorF("VScan = %d\n",mode->VScan) ;
|
|
ErrorF("Flags = %d\n",mode->Flags) ;
|
|
|
|
|
|
ErrorF("ClockIndex = %d\n",mode->ClockIndex) ;
|
|
ErrorF("SynthClock = %d\n",mode->SynthClock) ;
|
|
ErrorF("CrtcHDisplay = %d\n",mode->CrtcHDisplay) ;
|
|
ErrorF("CrtcHBlankStart = %d\n",mode->CrtcHBlankStart) ;
|
|
ErrorF("CrtcHSyncStart = %d\n",mode->CrtcHSyncStart) ;
|
|
ErrorF("CrtcHSyncEnd = %d\n",mode->CrtcHSyncEnd) ;
|
|
ErrorF("CrtcHBlankEnd = %d\n",mode->CrtcHBlankEnd) ;
|
|
ErrorF("CrtcHTotal = %d\n",mode->CrtcHTotal) ;
|
|
ErrorF("CrtcHSkew = %d\n",mode->CrtcHSkew) ;
|
|
ErrorF("CrtcVDisplay = %d\n",mode->CrtcVDisplay) ;
|
|
ErrorF("CrtcVBlankStart = %d\n",mode->CrtcVBlankStart) ;
|
|
ErrorF("CrtcVSyncStart = %d\n",mode->CrtcVSyncStart) ;
|
|
ErrorF("CrtcVSyncEnd = %d\n",mode->CrtcVSyncEnd) ;
|
|
ErrorF("CrtcVBlankEnd = %d\n",mode->CrtcVBlankEnd) ;
|
|
ErrorF("CrtcVTotal = %d\n",mode->CrtcVTotal) ;
|
|
ErrorF("CrtcHAdjusted = %s\n",(mode->CrtcHAdjusted)?"TRUE":"FALSE") ;
|
|
ErrorF("CrtcVAdjusted = %s\n",(mode->CrtcVAdjusted)?"TRUE":"FALSE") ;
|
|
ErrorF("PrivSize = %d\n",mode->PrivSize) ;
|
|
/* INT32 * Private; */
|
|
ErrorF("PrivFlags = %d\n",mode->PrivFlags) ;
|
|
ErrorF("HSync = %8.3f\n",mode->HSync) ;
|
|
ErrorF("VRefresh = %8.3f\n",mode->VRefresh) ;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
XGIDumpMonPtr(MonPtr pMonitor)
|
|
{
|
|
int i, j ;
|
|
DisplayModePtr mode;
|
|
|
|
#ifdef DEBUG5
|
|
ErrorF("XGIDumpMonPtr() ... \n") ;
|
|
if( pMonitor == NULL )
|
|
{
|
|
ErrorF("pMonitor is NULL\n") ;
|
|
}
|
|
|
|
ErrorF("id = %s, vendor = %s model = %s\n",pMonitor->id,pMonitor->vendor,pMonitor->model) ;
|
|
ErrorF("nHsync = %d\n",pMonitor->nHsync) ;
|
|
ErrorF("nVrefresh = %d\n",pMonitor->nVrefresh) ;
|
|
for( i = 0 ; i < MAX_HSYNC ; i++ )
|
|
{
|
|
ErrorF("hsync[%d] = (%8.3f,%8.3f)\n",i,pMonitor->hsync[i].lo,pMonitor->hsync[i].hi) ;
|
|
}
|
|
for( i = 0 ; i < MAX_VREFRESH ; i++ )
|
|
{
|
|
ErrorF("vrefresh[%d] = (%8.3f,%8.3f)\n",i,pMonitor->vrefresh[i].lo,pMonitor->vrefresh[i].hi) ;
|
|
}
|
|
/*
|
|
DisplayModePtr Modes;
|
|
DisplayModePtr Last;
|
|
Gamma gamma;
|
|
*/
|
|
ErrorF("widthmm = %d, heightmm = %d\n",
|
|
pMonitor->widthmm, pMonitor->heightmm ) ;
|
|
ErrorF("options = %p, DDC = %p\n",pMonitor->options,pMonitor->DDC) ;
|
|
mode = pMonitor->Modes ;
|
|
#if 0
|
|
while(1)
|
|
{
|
|
XGIDumpModePtr(mode) ;
|
|
if( mode == pMonitor->Last)
|
|
{
|
|
break ;
|
|
}
|
|
mode = mode->next ;
|
|
}
|
|
#endif /* 0 */
|
|
#endif /* DEBUG5 */
|
|
}
|
|
|
|
/* Mandatory */
|
|
static Bool
|
|
XGIPreInit(ScrnInfoPtr pScrn, int flags)
|
|
{
|
|
XGIPtr pXGI;
|
|
MessageType from;
|
|
/* unsigned char usScratchCR17, CR5F;
|
|
unsigned char usScratchCR32, usScratchCR63;
|
|
unsigned char usScratchSR1F; */
|
|
unsigned char tmpval;
|
|
unsigned long int i;
|
|
int temp;
|
|
ClockRangePtr clockRanges;
|
|
int pix24flags;
|
|
int fd;
|
|
struct fb_fix_screeninfo fix;
|
|
|
|
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = NULL;
|
|
#endif
|
|
#if defined(XGIMERGED) || defined(XGIDUALHEAD)
|
|
DisplayModePtr first, p, n;
|
|
#endif
|
|
unsigned char srlockReg,crlockReg;
|
|
/* unsigned char tempreg; */
|
|
|
|
vbeInfoPtr pVbe;
|
|
VbeInfoBlock *vbe;
|
|
|
|
/****************** Code Start ***********************/
|
|
|
|
DumpDDIName("XGIPreInit\n") ;
|
|
|
|
//inXGIIDXREG(XGICR, 0x4D, tmpval);
|
|
//tmpval = tmpval | 0x05;
|
|
//outXGIIDXREG(XGICR, 0x4D, tmpval);
|
|
|
|
if(flags & PROBE_DETECT)
|
|
{
|
|
if(xf86LoadSubModule(pScrn, "vbe"))
|
|
{
|
|
int index = xf86GetEntityInfo(pScrn->entityList[0])->index;
|
|
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
if((pVbe = VBEInit(NULL,index)))
|
|
{
|
|
#else
|
|
if((pVbe = VBEExtendedInit(NULL,index,0)))
|
|
{
|
|
#endif
|
|
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
|
|
vbeFree(pVbe);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Note: This function is only called once at server startup, and
|
|
* not at the start of each server generation. This means that
|
|
* only things that are persistent across server generations can
|
|
* be initialised here. xf86Screens[] is the array of all screens,
|
|
* (pScrn is a pointer to one of these). Privates allocated using
|
|
* xf86AllocateScrnInfoPrivateIndex() are too, and should be used
|
|
* for data that must persist across server generations.
|
|
*
|
|
* Per-generation data should be allocated with
|
|
* AllocateScreenPrivateIndex() from the ScreenInit() function.
|
|
*/
|
|
|
|
/* Check the number of entities, and fail if it isn't one. */
|
|
if(pScrn->numEntities != 1)
|
|
{
|
|
XGIErrorLog(pScrn, "Number of entities is not 1\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* The vgahw module should be loaded here when needed */
|
|
if(!xf86LoadSubModule(pScrn, "vgahw"))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not load vgahw module\n");
|
|
return FALSE;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(vgahwSymbols, NULL);
|
|
|
|
/* Due to the liberal license terms this is needed for
|
|
* keeping the copyright notice readable and intact in
|
|
* binary distributions. Removing this is a copyright
|
|
* infringement. Please read the license terms above.
|
|
*/
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGI driver (%d/%02d/%02d-%d)\n",
|
|
XGIDRIVERVERSIONYEAR + 2000, XGIDRIVERVERSIONMONTH,
|
|
XGIDRIVERVERSIONDAY, XGIDRIVERREVISION);
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Copyright (C) 2001-2004 Thomas Winischhofer <thomas@winischhofer.net> and others\n");
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Compiled for XFree86 %d.%d.%d.%d\n",
|
|
XF86_VERSION_MAJOR, XF86_VERSION_MINOR,
|
|
XF86_VERSION_PATCH, XF86_VERSION_SNAP);
|
|
|
|
#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
if(xf86GetVersion() != XF86_VERSION_CURRENT)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"This version of the driver is not compiled for this version of XFree86!\n");
|
|
}
|
|
#endif
|
|
|
|
/* Allocate a vgaHWRec */
|
|
if(!vgaHWGetHWRec(pScrn))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not allocate VGA private\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Allocate the XGIRec driverPrivate */
|
|
if(!XGIGetRec(pScrn))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not allocate memory for pXGI private\n");
|
|
return FALSE;
|
|
}
|
|
pXGI = XGIPTR(pScrn);
|
|
pXGI->pScrn = pScrn;
|
|
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
pXGI->IODBase = 0;
|
|
#else
|
|
pXGI->IODBase = pScrn->domainIOBase;
|
|
#endif
|
|
|
|
/* Get the entity, and make sure it is PCI. */
|
|
pXGI->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
|
|
if(pXGI->pEnt->location.type != BUS_PCI)
|
|
{
|
|
XGIErrorLog(pScrn, "Entity's bus type is not PCI\n");
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* Allocate an entity private if necessary */
|
|
if(xf86IsEntityShared(pScrn->entityList[0]))
|
|
{
|
|
pXGIEnt = xf86GetEntityPrivate(pScrn->entityList[0],
|
|
XGIEntityIndex)->ptr;
|
|
pXGI->entityPrivate = pXGIEnt;
|
|
|
|
/* If something went wrong, quit here */
|
|
if((pXGIEnt->DisableDual) || (pXGIEnt->ErrorAfterFirst))
|
|
{
|
|
XGIErrorLog(pScrn, "First head encountered fatal error, can't continue\n");
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Find the PCI info for this screen */
|
|
pXGI->PciInfo = xf86GetPciInfoForEntity(pXGI->pEnt->index);
|
|
pXGI->PciTag =
|
|
pXGI->xgi_HwDevExt.PciTag =
|
|
pciTag(pXGI->PciInfo->bus,
|
|
pXGI->PciInfo->device,
|
|
pXGI->PciInfo->func);
|
|
|
|
pXGI->Primary = xf86IsPrimaryPci(pXGI->PciInfo);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"This adapter is %s display adapter\n",
|
|
(pXGI->Primary ? "primary" : "secondary"));
|
|
|
|
if(pXGI->Primary)
|
|
{
|
|
VGAHWPTR(pScrn)->MapSize = 0x10000; /* Standard 64k VGA window */
|
|
if(!vgaHWMapMem(pScrn))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not map VGA memory\n");
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
vgaHWGetIOBase(VGAHWPTR(pScrn));
|
|
|
|
/* We "patch" the PIOOffset inside vgaHW in order to force
|
|
* the vgaHW module to use our relocated i/o ports.
|
|
*/
|
|
VGAHWPTR(pScrn)->PIOOffset = pXGI->IODBase + (pXGI->PciInfo->ioBase[2] & 0xFFFC) - 0x380;
|
|
|
|
pXGI->pInt = NULL;
|
|
if(!pXGI->Primary)
|
|
{
|
|
#if !defined(__alpha__)
|
|
#if !defined(__powerpc__)
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Initializing display adapter through int10\n");
|
|
|
|
if(xf86LoadSubModule(pScrn, "int10"))
|
|
{
|
|
xf86LoaderReqSymLists(int10Symbols, NULL);
|
|
pXGI->pInt = xf86InitInt10(pXGI->pEnt->index);
|
|
}
|
|
else
|
|
{
|
|
XGIErrorLog(pScrn, "Could not load int10 module\n");
|
|
}
|
|
#endif /* !defined(__powerpc__) */
|
|
#endif /* !defined(__alpha__) */
|
|
}
|
|
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
{
|
|
resRange vgamem[] = {
|
|
{ResShrMemBlock,0xA0000,0xAFFFF},
|
|
{ResShrMemBlock,0xB0000,0xB7FFF},
|
|
{ResShrMemBlock,0xB8000,0xBFFFF},
|
|
_END };
|
|
xf86SetOperatingState(vgamem, pXGI->pEnt->index, ResUnusedOpr);
|
|
}
|
|
#else
|
|
xf86SetOperatingState(resVgaMem, pXGI->pEnt->index, ResUnusedOpr);
|
|
#endif
|
|
|
|
/* Operations for which memory access is required */
|
|
pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
|
|
/* Operations for which I/O access is required */
|
|
pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
|
|
|
|
/* The ramdac module should be loaded here when needed */
|
|
if(!xf86LoadSubModule(pScrn, "ramdac"))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not load ramdac module\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(ramdacSymbols, NULL);
|
|
|
|
/* Set pScrn->monitor */
|
|
pScrn->monitor = pScrn->confScreen->monitor;
|
|
|
|
/*
|
|
* Set the Chipset and ChipRev, allowing config file entries to
|
|
* override. DANGEROUS!
|
|
*/
|
|
if(pXGI->pEnt->device->chipset && *pXGI->pEnt->device->chipset)
|
|
{
|
|
PDEBUG(ErrorF(" --- Chipset 1 \n"));
|
|
pScrn->chipset = pXGI->pEnt->device->chipset;
|
|
pXGI->Chipset = xf86StringToToken(XGIChipsets, pScrn->chipset);
|
|
from = X_CONFIG;
|
|
}
|
|
else if(pXGI->pEnt->device->chipID >= 0)
|
|
{
|
|
PDEBUG(ErrorF(" --- Chipset 2 \n"));
|
|
pXGI->Chipset = pXGI->pEnt->device->chipID;
|
|
pScrn->chipset = (char *)xf86TokenToString(XGIChipsets, pXGI->Chipset);
|
|
|
|
from = X_CONFIG;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
|
|
pXGI->Chipset);
|
|
}
|
|
else
|
|
{
|
|
PDEBUG(ErrorF(" --- Chipset 3 \n"));
|
|
from = X_PROBED;
|
|
pXGI->Chipset = pXGI->PciInfo->chipType;
|
|
pScrn->chipset = (char *)xf86TokenToString(XGIChipsets, pXGI->Chipset);
|
|
}
|
|
if(pXGI->pEnt->device->chipRev >= 0)
|
|
{
|
|
pXGI->ChipRev = pXGI->pEnt->device->chipRev;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
|
|
pXGI->ChipRev);
|
|
}
|
|
else
|
|
{
|
|
pXGI->ChipRev = pXGI->PciInfo->chipRev;
|
|
}
|
|
pXGI->xgi_HwDevExt.jChipRevision = pXGI->ChipRev;
|
|
|
|
PDEBUG(ErrorF(" --- Chipset : %s \n", pScrn->chipset));
|
|
|
|
|
|
pXGI->XGI6326Flags = 0;
|
|
|
|
/*
|
|
* This shouldn't happen because such problems should be caught in
|
|
* XGIProbe(), but check it just in case.
|
|
*/
|
|
if(pScrn->chipset == NULL)
|
|
{
|
|
XGIErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pXGI->Chipset);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
if(pXGI->Chipset < 0)
|
|
{
|
|
XGIErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Determine chipset and VGA engine type */
|
|
pXGI->ChipFlags = 0;
|
|
pXGI->XGI_SD_Flags = 0;
|
|
pXGI->HWCursorMBufNum = pXGI->HWCursorCBufNum = 0;
|
|
|
|
switch(pXGI->Chipset)
|
|
{
|
|
|
|
case PCI_CHIP_XGIXG40:
|
|
case PCI_CHIP_XGIXG20:
|
|
pXGI->xgi_HwDevExt.jChipType = XG40;
|
|
pXGI->VGAEngine = XGI_XGX_VGA;
|
|
pXGI->myCR63 = 0x63;
|
|
pXGI->mmioSize = 64;
|
|
break;
|
|
default:
|
|
pXGI->xgi_HwDevExt.jChipType = XGI_OLD;
|
|
pXGI->VGAEngine = XGI_OLD_VGA;
|
|
pXGI->mmioSize = 64;
|
|
break;
|
|
}
|
|
|
|
/* load frame_buffer */
|
|
|
|
FbDevExist = FALSE;
|
|
if( pXGI->Chipset != PCI_CHIP_XGIXG20 )
|
|
{
|
|
if( (fd = open("/dev/fb", 'r')) != -1)
|
|
{
|
|
PDEBUG(ErrorF("--- open /dev/fb.... \n"));
|
|
ioctl(fd,FBIOGET_FSCREENINFO, &fix);
|
|
if (fix.accel == FB_ACCEL_XGI_GLAMOUR)
|
|
{
|
|
PDEBUG(ErrorF("--- fix.accel.... \n"));
|
|
FbDevExist = TRUE;
|
|
}
|
|
else
|
|
PDEBUG(ErrorF("--- no fix.accel.... 0x%08lx \n", fix.accel));
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
/* Now check if xgifb is loaded. Since xgifb only supports
|
|
* the 300 and 315 series, we only do this for these chips.
|
|
* We use this for checking where xgifb starts its memory
|
|
* heap in order to automatically detect the correct MaxXFBMem
|
|
* setting (which normally is given by the option of the same name).
|
|
* Under kernel 2.4.y, that only works if xgifb is completely
|
|
* running, ie with a video mode because the fbdev will not be
|
|
* installed otherwise. Under 2.5 and later, xgifb will install
|
|
* the framebuffer device in any way and running it with mode=none
|
|
* is no longer supported (or necessary).
|
|
*/
|
|
|
|
pXGI->donttrustpdc = FALSE;
|
|
pXGI->xgifbpdc = 0xff;
|
|
pXGI->xgifbpdca = 0xff;
|
|
pXGI->xgifblcda = 0xff;
|
|
pXGI->xgifbscalelcd = -1;
|
|
pXGI->xgifbspecialtiming = CUT_NONE;
|
|
pXGI->xgifb_haveemi = FALSE;
|
|
pXGI->OldMode = 0;
|
|
pXGI->xgifbfound = FALSE;
|
|
|
|
/*
|
|
* The first thing we should figure out is the depth, bpp, etc.
|
|
* Additionally, determine the size of the HWCursor memory area.
|
|
*/
|
|
switch(pXGI->VGAEngine)
|
|
{
|
|
case XGI_XGX_VGA:
|
|
pXGI->CursorSize = 4096;
|
|
pix24flags = Support32bppFb;
|
|
break;
|
|
default:
|
|
pXGI->CursorSize = 2048;
|
|
pix24flags = Support24bppFb;
|
|
break;
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* In case of Dual Head, we need to determine if we are the "master" head or
|
|
* the "slave" head. In order to do that, we set PrimInit to DONE in the
|
|
* shared entity at the end of the first initialization. The second
|
|
* initialization then knows that some things have already been done. THIS
|
|
* ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER!
|
|
*/
|
|
|
|
if(xf86IsEntityShared(pScrn->entityList[0]))
|
|
{
|
|
if(pXGIEnt->lastInstance > 0)
|
|
{
|
|
if(!xf86IsPrimInitDone(pScrn->entityList[0]))
|
|
{
|
|
/* First Head (always CRT2) */
|
|
pXGI->SecondHead = FALSE;
|
|
pXGIEnt->pScrn_1 = pScrn;
|
|
pXGIEnt->CRT1ModeNo = pXGIEnt->CRT2ModeNo = -1;
|
|
pXGIEnt->CRT2ModeSet = FALSE;
|
|
pXGI->DualHeadMode = TRUE;
|
|
pXGIEnt->DisableDual = FALSE;
|
|
pXGIEnt->BIOS = NULL;
|
|
pXGIEnt->ROM661New = FALSE;
|
|
pXGIEnt->XGI_Pr = NULL;
|
|
pXGIEnt->RenderAccelArray = NULL;
|
|
}
|
|
else
|
|
{
|
|
/* Second Head (always CRT1) */
|
|
pXGI->SecondHead = TRUE;
|
|
pXGIEnt->pScrn_2 = pScrn;
|
|
pXGI->DualHeadMode = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Only one screen in config file - disable dual head mode */
|
|
pXGI->SecondHead = FALSE;
|
|
pXGI->DualHeadMode = FALSE;
|
|
pXGIEnt->DisableDual = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Entity is not shared - disable dual head mode */
|
|
pXGI->SecondHead = FALSE;
|
|
pXGI->DualHeadMode = FALSE;
|
|
}
|
|
#endif
|
|
|
|
pXGI->ForceCursorOff = FALSE;
|
|
|
|
/* Allocate XGI_Private (for mode switching code) and initialize it */
|
|
pXGI->XGI_Pr = NULL;
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt)
|
|
{
|
|
if(pXGIEnt->XGI_Pr) pXGI->XGI_Pr = pXGIEnt->XGI_Pr;
|
|
}
|
|
#endif
|
|
if(!pXGI->XGI_Pr)
|
|
{
|
|
if(!(pXGI->XGI_Pr = xnfcalloc(sizeof(XGI_Private), 1)))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not allocate memory for XGI_Pr private\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->XGI_Pr = pXGI->XGI_Pr;
|
|
#endif
|
|
memset(pXGI->XGI_Pr, 0, sizeof(XGI_Private));
|
|
pXGI->XGI_Pr->XGI_Backup70xx = 0xff;
|
|
pXGI->XGI_Pr->XGI_CHOverScan = -1;
|
|
pXGI->XGI_Pr->XGI_ChSW = FALSE;
|
|
pXGI->XGI_Pr->XGI_CustomT = CUT_NONE;
|
|
pXGI->XGI_Pr->PanelSelfDetected = FALSE;
|
|
pXGI->XGI_Pr->UsePanelScaler = -1;
|
|
pXGI->XGI_Pr->CenterScreen = -1;
|
|
pXGI->XGI_Pr->CRT1UsesCustomMode = FALSE;
|
|
pXGI->XGI_Pr->PDC = pXGI->XGI_Pr->PDCA = -1;
|
|
pXGI->XGI_Pr->LVDSHL = -1;
|
|
pXGI->XGI_Pr->HaveEMI = FALSE;
|
|
pXGI->XGI_Pr->HaveEMILCD = FALSE;
|
|
pXGI->XGI_Pr->OverruleEMI = FALSE;
|
|
pXGI->XGI_Pr->XGI_SensibleSR11 = FALSE;
|
|
if(pXGI->xgi_HwDevExt.jChipType >= XGI_661)
|
|
{
|
|
pXGI->XGI_Pr->XGI_SensibleSR11 = TRUE;
|
|
}
|
|
pXGI->XGI_Pr->XGI_MyCR63 = pXGI->myCR63;
|
|
}
|
|
|
|
/* Get our relocated IO registers */
|
|
pXGI->RelIO = (XGIIOADDRESS)((pXGI->PciInfo->ioBase[2] & 0xFFFC) + pXGI->IODBase);
|
|
pXGI->xgi_HwDevExt.pjIOAddress = (XGIIOADDRESS)(pXGI->RelIO + 0x30);
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Relocated IO registers at 0x%lX\n",
|
|
(unsigned long)pXGI->RelIO);
|
|
|
|
/* Initialize XGI Port Reg definitions for externally used
|
|
* init.c/init301.c functions.
|
|
*/
|
|
XGIRegInit(pXGI->XGI_Pr, pXGI->RelIO + 0x30);
|
|
|
|
if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags))
|
|
{
|
|
XGIErrorLog(pScrn, "xf86SetDepthBpp() error\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check that the returned depth is one we support */
|
|
temp = 0;
|
|
switch(pScrn->depth)
|
|
{
|
|
case 8:
|
|
case 16:
|
|
case 24:
|
|
#if !defined(__powerpc__)
|
|
case 15:
|
|
#endif
|
|
break;
|
|
default:
|
|
temp = 1;
|
|
}
|
|
|
|
if(temp)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"Given color depth (%d) is not supported by this driver/chipset\n",
|
|
pScrn->depth);
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PrintDepthBpp(pScrn);
|
|
|
|
/* Get the depth24 pixmap format */
|
|
if(pScrn->depth == 24 && pix24bpp == 0)
|
|
{
|
|
pix24bpp = xf86GetBppFromDepth(pScrn, 24);
|
|
}
|
|
|
|
/*
|
|
* This must happen after pScrn->display has been set because
|
|
* xf86SetWeight references it.
|
|
*/
|
|
if(pScrn->depth > 8)
|
|
{
|
|
/* The defaults are OK for us */
|
|
rgb zeros =
|
|
{0, 0, 0};
|
|
|
|
if(!xf86SetWeight(pScrn, zeros, zeros))
|
|
{
|
|
XGIErrorLog(pScrn, "xf86SetWeight() error\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
Bool ret = FALSE;
|
|
switch(pScrn->depth)
|
|
{
|
|
case 15:
|
|
if((pScrn->weight.red != 5) ||
|
|
(pScrn->weight.green != 5) ||
|
|
(pScrn->weight.blue != 5)) ret = TRUE;
|
|
break;
|
|
case 16:
|
|
if((pScrn->weight.red != 5) ||
|
|
(pScrn->weight.green != 6) ||
|
|
(pScrn->weight.blue != 5)) ret = TRUE;
|
|
break;
|
|
case 24:
|
|
if((pScrn->weight.red != 8) ||
|
|
(pScrn->weight.green != 8) ||
|
|
(pScrn->weight.blue != 8)) ret = TRUE;
|
|
break;
|
|
}
|
|
if(ret)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"RGB weight %d%d%d at depth %d not supported by hardware\n",
|
|
(int)pScrn->weight.red, (int)pScrn->weight.green,
|
|
(int)pScrn->weight.blue, pScrn->depth);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set the current layout parameters */
|
|
pXGI->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
|
|
pXGI->CurrentLayout.depth = pScrn->depth;
|
|
/* (Inside this function, we can use pScrn's contents anyway) */
|
|
|
|
if(!xf86SetDefaultVisual(pScrn, -1))
|
|
{
|
|
XGIErrorLog(pScrn, "xf86SetDefaultVisual() error\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* We don't support DirectColor at > 8bpp */
|
|
if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"Given default visual (%s) is not supported at depth %d\n",
|
|
xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* Due to palette & timing problems we don't support 8bpp in DHM */
|
|
if((pXGI->DualHeadMode) && (pScrn->bitsPerPixel == 8))
|
|
{
|
|
XGIErrorLog(pScrn, "Color depth 8 not supported in Dual Head mode.\n");
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* The cmap layer needs this to be initialised.
|
|
*/
|
|
{
|
|
Gamma zeros =
|
|
{0.0, 0.0, 0.0};
|
|
|
|
if(!xf86SetGamma(pScrn, zeros))
|
|
{
|
|
XGIErrorLog(pScrn, "xf86SetGamma() error\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* We use a programamble clock */
|
|
pScrn->progClock = TRUE;
|
|
|
|
/* Set the bits per RGB for 8bpp mode */
|
|
if(pScrn->depth == 8)
|
|
{
|
|
pScrn->rgbBits = 6;
|
|
}
|
|
|
|
from = X_DEFAULT;
|
|
|
|
/* Unlock registers */
|
|
xgiSaveUnlockExtRegisterLock(pXGI, &srlockReg, &crlockReg);
|
|
|
|
/* Read BIOS for 300 and 315/330 series customization */
|
|
pXGI->xgi_HwDevExt.pjVirtualRomBase = NULL;
|
|
pXGI->BIOS = NULL;
|
|
pXGI->xgi_HwDevExt.UseROM = FALSE;
|
|
pXGI->ROM661New = FALSE;
|
|
|
|
/* Evaluate options */
|
|
xgiOptions(pScrn);
|
|
|
|
#ifdef XGIMERGED
|
|
/* Due to palette & timing problems we don't support 8bpp in MFBM */
|
|
if((pXGI->MergedFB) && (pScrn->bitsPerPixel == 8))
|
|
{
|
|
XGIErrorLog(pScrn, "MergedFB: Color depth 8 not supported, %s\n", mergeddisstr);
|
|
pXGI->MergedFB = pXGI->MergedFBAuto = FALSE;
|
|
}
|
|
#endif
|
|
|
|
/* Do basic configuration */
|
|
|
|
XGISetup(pScrn);
|
|
XGI_InitHwDevInfo(pScrn);
|
|
|
|
from = X_PROBED;
|
|
if(pXGI->pEnt->device->MemBase != 0)
|
|
{
|
|
/*
|
|
* XXX Should check that the config file value matches one of the
|
|
* PCI base address values.
|
|
*/
|
|
pXGI->FbAddress = pXGI->pEnt->device->MemBase;
|
|
from = X_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
pXGI->FbAddress = pXGI->PciInfo->memBase[0] & 0xFFFFFFF0;
|
|
}
|
|
|
|
pXGI->realFbAddress = pXGI->FbAddress;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n",
|
|
(unsigned long)pXGI->FbAddress);
|
|
else
|
|
#endif
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
|
|
(unsigned long)pXGI->FbAddress);
|
|
|
|
if(pXGI->pEnt->device->IOBase != 0)
|
|
{
|
|
/*
|
|
* XXX Should check that the config file value matches one of the
|
|
* PCI base address values.
|
|
*/
|
|
pXGI->IOAddress = pXGI->pEnt->device->IOBase;
|
|
from = X_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
pXGI->IOAddress = pXGI->PciInfo->memBase[1] & 0xFFFFFFF0;
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n",
|
|
(unsigned long)pXGI->IOAddress, pXGI->mmioSize);
|
|
pXGI->xgi_HwDevExt.bIntegratedMMEnabled = TRUE;
|
|
|
|
/* Register the PCI-assigned resources. */
|
|
if(xf86RegisterResources(pXGI->pEnt->index, NULL, ResExclusive))
|
|
{
|
|
XGIErrorLog(pScrn, "xf86RegisterResources() found resource conflicts\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
from = X_PROBED;
|
|
if(pXGI->pEnt->device->videoRam != 0)
|
|
{
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Option \"VideoRAM\" ignored\n");
|
|
}
|
|
|
|
pXGI->RealVideoRam = pScrn->videoRam;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n",
|
|
pScrn->videoRam);
|
|
|
|
pXGI->FbMapSize = pXGI->availMem = pScrn->videoRam * 1024;
|
|
pXGI->xgi_HwDevExt.ulVideoMemorySize = pScrn->videoRam * 1024;
|
|
pXGI->xgi_HwDevExt.bSkipDramSizing = TRUE;
|
|
|
|
/* Calculate real availMem according to Accel/TurboQueue and
|
|
* HWCursur setting. Also, initialize some variables used
|
|
* in other modules.
|
|
*/
|
|
|
|
pXGI->cursorOffset = 0;
|
|
pXGI->CurARGBDest = NULL;
|
|
pXGI->CurMonoSrc = NULL;
|
|
pXGI->CurFGCol = pXGI->CurBGCol = 0;
|
|
|
|
switch(pXGI->VGAEngine)
|
|
{
|
|
default:
|
|
/* cursorOffset not used in cursor functions for 530 and
|
|
* older chips, because the cursor is *above* the TQ.
|
|
* On 5597 and older revisions of the 6326, the TQ is
|
|
* max 32K, on newer 6326 revisions and the 530 either 30
|
|
* (or 32?) or 62K (or 64?). However, to make sure, we
|
|
* use only 30K (or 32?), but reduce the available memory
|
|
* by 64, and locate the TQ at the beginning of this last
|
|
* 64K block. (We do this that way even when using the
|
|
* HWCursor, because the cursor only takes 2K and the
|
|
* queue does not seem to last that far anyway.)
|
|
* The TQ must be located at 32KB boundaries.
|
|
*/
|
|
if(pXGI->RealVideoRam < 3072)
|
|
{
|
|
if(pXGI->TurboQueue)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Not enough video RAM for TurboQueue. TurboQueue disabled\n");
|
|
pXGI->TurboQueue = FALSE;
|
|
}
|
|
}
|
|
pXGI->CmdQueMaxLen = 32;
|
|
if(pXGI->TurboQueue)
|
|
{
|
|
pXGI->availMem -= (64*1024);
|
|
pXGI->CmdQueMaxLen = 900; /* To make sure; should be 992 */
|
|
}
|
|
else if(pXGI->HWCursor)
|
|
{
|
|
pXGI->availMem -= pXGI->CursorSize;
|
|
}
|
|
|
|
pXGI->CmdQueLenMask = (pXGI->TurboQueue) ? 0x7FFF : 0x003F;
|
|
|
|
/* This is to be subtracted from MMIO queue length register contents
|
|
* for getting the real Queue length.
|
|
*/
|
|
pXGI->CmdQueLenFix = (pXGI->TurboQueue) ? 32 : 0;
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* In dual head mode, we share availMem equally - so align it
|
|
* to 8KB; this way, the address of the FB of the second
|
|
* head is aligned to 4KB for mapping.
|
|
*/
|
|
if(pXGI->DualHeadMode)
|
|
pXGI->availMem &= 0xFFFFE000;
|
|
#endif
|
|
|
|
/* Check MaxXFBMem setting */
|
|
#ifdef XGIDUALHEAD
|
|
/* Since DRI is not supported in dual head mode, we
|
|
don't need the MaxXFBMem setting. */
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->maxxfbmem)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"MaxXFBMem not used in Dual Head mode. Using all VideoRAM.\n");
|
|
}
|
|
pXGI->maxxfbmem = pXGI->availMem;
|
|
}
|
|
else
|
|
#endif
|
|
if(pXGI->maxxfbmem)
|
|
{
|
|
if(pXGI->maxxfbmem > pXGI->availMem)
|
|
{
|
|
if(pXGI->xgifbMem)
|
|
{
|
|
pXGI->maxxfbmem = pXGI->xgifbMem * 1024;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Invalid MaxXFBMem setting. Using xgifb heap start information\n");
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Invalid MaxXFBMem setting. Using all VideoRAM for framebuffer\n");
|
|
pXGI->maxxfbmem = pXGI->availMem;
|
|
}
|
|
}
|
|
else if(pXGI->xgifbMem)
|
|
{
|
|
if(pXGI->maxxfbmem > pXGI->xgifbMem * 1024)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"MaxXFBMem beyond xgifb heap start. Using xgifb heap start\n");
|
|
pXGI->maxxfbmem = pXGI->xgifbMem * 1024;
|
|
}
|
|
}
|
|
}
|
|
else if(pXGI->xgifbMem)
|
|
{
|
|
pXGI->maxxfbmem = pXGI->xgifbMem * 1024;
|
|
}
|
|
else pXGI->maxxfbmem = pXGI->availMem;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %ldK of framebuffer memory\n",
|
|
pXGI->maxxfbmem / 1024);
|
|
|
|
|
|
/* There are some machines out there which require a special
|
|
* setup of the GPIO registers in order to make the Chrontel
|
|
* work. Try to find out if we're running on such a machine.
|
|
* Furthermore, there is some highly customized hardware,
|
|
* which requires some non-standard LVDS timing. Since the
|
|
* vendors don't seem to care about PCI subsystem ID's we
|
|
* need to find out using the BIOS version and date strings.
|
|
*/
|
|
pXGI->XGI_Pr->XGI_ChSW = FALSE;
|
|
|
|
if(pXGI->XGI_Pr->XGI_CustomT == CUT_NONE)
|
|
{
|
|
int i = 0, j;
|
|
unsigned short bversptr = 0;
|
|
BOOLEAN footprint;
|
|
unsigned long chksum = 0;
|
|
|
|
if(pXGI->xgi_HwDevExt.UseROM)
|
|
{
|
|
bversptr = pXGI->BIOS[0x16] | (pXGI->BIOS[0x17] << 8);
|
|
for(i=0; i<32768; i++) chksum += pXGI->BIOS[i];
|
|
}
|
|
|
|
i = 0;
|
|
do
|
|
{
|
|
if( (mycustomttable[i].chipID == pXGI->xgi_HwDevExt.jChipType) &&
|
|
((!strlen(mycustomttable[i].biosversion)) ||
|
|
(pXGI->xgi_HwDevExt.UseROM &&
|
|
(!strncmp(mycustomttable[i].biosversion, (char *)&pXGI->BIOS[bversptr],
|
|
strlen(mycustomttable[i].biosversion))))) &&
|
|
((!strlen(mycustomttable[i].biosdate)) ||
|
|
(pXGI->xgi_HwDevExt.UseROM &&
|
|
(!strncmp(mycustomttable[i].biosdate, (char *)&pXGI->BIOS[0x2c],
|
|
strlen(mycustomttable[i].biosdate))))) &&
|
|
((!mycustomttable[i].bioschksum) ||
|
|
(pXGI->xgi_HwDevExt.UseROM &&
|
|
(mycustomttable[i].bioschksum == chksum))) &&
|
|
(mycustomttable[i].pcisubsysvendor == pXGI->PciInfo->subsysVendor) &&
|
|
(mycustomttable[i].pcisubsyscard == pXGI->PciInfo->subsysCard) )
|
|
{
|
|
footprint = TRUE;
|
|
for(j=0; j<5; j++)
|
|
{
|
|
if(mycustomttable[i].biosFootprintAddr[j])
|
|
{
|
|
if(pXGI->xgi_HwDevExt.UseROM)
|
|
{
|
|
if(pXGI->BIOS[mycustomttable[i].biosFootprintAddr[j]] !=
|
|
mycustomttable[i].biosFootprintData[j])
|
|
footprint = FALSE;
|
|
}
|
|
else footprint = FALSE;
|
|
}
|
|
}
|
|
if(footprint)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Identified %s %s, special timing applies\n",
|
|
mycustomttable[i].vendorName, mycustomttable[i].cardName);
|
|
pXGI->XGI_Pr->XGI_CustomT = mycustomttable[i].SpecialID;
|
|
break;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
while(mycustomttable[i].chipID);
|
|
}
|
|
|
|
/* Handle ForceCRT1 option */
|
|
if(pXGI->forceCRT1 != -1)
|
|
{
|
|
if(pXGI->forceCRT1) pXGI->CRT1off = 0;
|
|
else pXGI->CRT1off = 1;
|
|
}
|
|
else pXGI->CRT1off = -1;
|
|
|
|
/* Detect video bridge and sense TV/VGA2 */
|
|
XGIVGAPreInit(pScrn);
|
|
|
|
/* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */
|
|
XGICRT1PreInit(pScrn);
|
|
|
|
/* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */
|
|
XGILCDPreInit(pScrn);
|
|
|
|
/* LCDA only supported under these conditions: */
|
|
if(pXGI->ForceCRT1Type == CRT1_LCDA)
|
|
{
|
|
if( ((pXGI->xgi_HwDevExt.jChipType != XGI_650) &&
|
|
(pXGI->xgi_HwDevExt.jChipType < XGI_661)) ||
|
|
(!(pXGI->XGI_Pr->XGI_VBType & (VB_XGI301C | VB_XGI302B | VB_XGI301LV | VB_XGI302LV))) )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Chipset/Video bridge does not support LCD-via-CRT1\n");
|
|
pXGI->ForceCRT1Type = CRT1_VGA;
|
|
}
|
|
else if(!(pXGI->VBFlags & CRT2_LCD))
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"No digitally connected LCD panel found, LCD-via-CRT1 disabled\n");
|
|
pXGI->ForceCRT1Type = CRT1_VGA;
|
|
}
|
|
}
|
|
|
|
/* Setup SD flags */
|
|
pXGI->XGI_SD_Flags |= XGI_SD_ADDLSUPFLAG;
|
|
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB )
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_SUPPORTTV;
|
|
}
|
|
|
|
#ifdef ENABLE_YPBPR
|
|
if(pXGI->XGI_Pr->XGI_VBType & (VB_XGI301|VB_XGI301B|VB_XGI302B))
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_SUPPORTHIVISION;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TWDEBUG /* @@@ TEST @@@ */
|
|
pXGI->XGI_SD_Flags |= XGI_SD_SUPPORTYPBPRAR;
|
|
xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n");
|
|
#endif
|
|
|
|
/* Detect CRT2-TV and PAL/NTSC mode */
|
|
XGITVPreInit(pScrn);
|
|
|
|
/* Detect CRT2-VGA */
|
|
XGICRT2PreInit(pScrn);
|
|
PDEBUG(ErrorF("3496 pXGI->VBFlags =%x\n",pXGI->VBFlags)) ;
|
|
/* Backup detected CRT2 devices */
|
|
pXGI->detectedCRT2Devices = pXGI->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR);
|
|
|
|
if(!(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPR))
|
|
{
|
|
if((pXGI->ForceTVType != -1) && (pXGI->ForceTVType & TV_YPBPR))
|
|
{
|
|
pXGI->ForceTVType = -1;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n");
|
|
}
|
|
}
|
|
|
|
if(!(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTHIVISION))
|
|
{
|
|
if((pXGI->ForceTVType != -1) && (pXGI->ForceTVType & TV_HIVISION))
|
|
{
|
|
pXGI->ForceTVType = -1;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n");
|
|
}
|
|
}
|
|
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB)
|
|
{
|
|
pXGI->XGI_SD_Flags |= (XGI_SD_SUPPORTPALMN | XGI_SD_SUPPORTNTSCJ);
|
|
}
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB )
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_SUPPORTTVPOS;
|
|
}
|
|
if(pXGI->XGI_Pr->XGI_VBType & (VB_XGI301|VB_XGI301B|VB_XGI301C|VB_XGI302B))
|
|
{
|
|
pXGI->XGI_SD_Flags |= (XGI_SD_SUPPORTSCART | XGI_SD_SUPPORTVGA2);
|
|
}
|
|
|
|
if( ((pXGI->xgi_HwDevExt.jChipType == XGI_650) ||
|
|
(pXGI->xgi_HwDevExt.jChipType >= XGI_661)) &&
|
|
(pXGI->XGI_Pr->XGI_VBType& (VB_XGI301C | VB_XGI302B | VB_XGI301LV | VB_XGI302LV)) &&
|
|
(pXGI->VBFlags & CRT2_LCD)&&
|
|
(pXGI->VESA != 1) )
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_SUPPORTLCDA;
|
|
}
|
|
else
|
|
{
|
|
/* Paranoia */
|
|
pXGI->ForceCRT1Type = CRT1_VGA;
|
|
}
|
|
|
|
pXGI->VBFlags |= pXGI->ForceCRT1Type;
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pXGI->XGI_SD_Flags);
|
|
#endif
|
|
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if((!pXGI->DualHeadMode) || (pXGI->SecondHead))
|
|
{
|
|
#endif
|
|
xf86DrvMsg(pScrn->scrnIndex, pXGI->CRT1gammaGiven ? X_CONFIG : X_INFO,
|
|
"CRT1 gamma correction is %s\n",
|
|
pXGI->CRT1gamma ? "enabled" : "disabled");
|
|
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
/* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB)
|
|
{
|
|
if(pXGI->ForceTVType != -1)
|
|
{
|
|
pXGI->VBFlags &= ~(TV_INTERFACE);
|
|
pXGI->VBFlags |= pXGI->ForceTVType;
|
|
if(pXGI->VBFlags & TV_YPBPR)
|
|
{
|
|
pXGI->VBFlags &= ~(TV_STANDARD);
|
|
pXGI->VBFlags &= ~(TV_YPBPRAR);
|
|
pXGI->VBFlags |= pXGI->ForceYPbPrType;
|
|
pXGI->VBFlags |= pXGI->ForceYPbPrAR;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Handle ForceCRT1 option (part 2) */
|
|
pXGI->CRT1changed = FALSE;
|
|
|
|
/* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB)
|
|
{
|
|
|
|
/* No CRT2 output? Then we NEED CRT1!
|
|
* We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH
|
|
*/
|
|
if( (!(pXGI->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) ||
|
|
( (pScrn->bitsPerPixel == 8) && ( pXGI->XGI_Pr->XGI_VBType & VB_XGI301LV302LV ) ) )
|
|
{
|
|
pXGI->CRT1off = 0;
|
|
}
|
|
/* No CRT2 output? Then we can't use Xv on CRT2 */
|
|
if(!(pXGI->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV)))
|
|
pXGI->XvOnCRT2 = FALSE;
|
|
|
|
}
|
|
else
|
|
{ /* no video bridge? */
|
|
|
|
/* Then we NEED CRT1... */
|
|
pXGI->CRT1off = 0;
|
|
/* ... and can't use CRT2 for Xv output */
|
|
pXGI->XvOnCRT2 = FALSE;
|
|
}
|
|
|
|
/* LCDA? Then we don't switch off CRT1 */
|
|
if(pXGI->VBFlags & CRT1_LCDA) pXGI->CRT1off = 0;
|
|
|
|
/* Handle TVStandard option */
|
|
if((pXGI->NonDefaultPAL != -1) || (pXGI->NonDefaultNTSC != -1))
|
|
{
|
|
if( !(pXGI->XGI_Pr->XGI_VBType& VB_XGIVB) )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"PALM, PALN and NTSCJ not supported on this hardware\n");
|
|
pXGI->NonDefaultPAL = pXGI->NonDefaultNTSC = -1;
|
|
pXGI->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ);
|
|
pXGI->XGI_SD_Flags &= ~(XGI_SD_SUPPORTPALMN | XGI_SD_SUPPORTNTSCJ);
|
|
}
|
|
}
|
|
|
|
#ifdef XGI_CP
|
|
XGI_CP_DRIVER_RECONFIGOPT
|
|
#endif
|
|
PDEBUG(ErrorF("3629 pXGI->VBFlags =%x\n",pXGI->VBFlags)) ;
|
|
/* Do some checks */
|
|
if(pXGI->OptTVOver != -1)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"CHTVOverscan only supported on CHRONTEL 70xx\n");
|
|
pXGI->UseCHOverScan = -1;
|
|
}
|
|
else pXGI->UseCHOverScan = -1;
|
|
|
|
if(pXGI->xgitvedgeenhance != -1)
|
|
{
|
|
if(!(pXGI->XGI_Pr->XGI_VBType & VB_XGI301))
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGITVEdgeEnhance only supported on XGI301\n");
|
|
pXGI->xgitvedgeenhance = -1;
|
|
}
|
|
}
|
|
if(pXGI->xgitvsaturation != -1)
|
|
{
|
|
if(pXGI->XGI_Pr->XGI_VBType & VB_XGI301)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGITVSaturation not supported on XGI301\n");
|
|
pXGI->xgitvsaturation = -1;
|
|
}
|
|
}
|
|
|
|
/* Do some MergedFB mode initialisation */
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
pXGI->CRT2pScrn = xalloc(sizeof(ScrnInfoRec));
|
|
if(!pXGI->CRT2pScrn)
|
|
{
|
|
XGIErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr);
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
else
|
|
{
|
|
memcpy(pXGI->CRT2pScrn, pScrn, sizeof(ScrnInfoRec));
|
|
}
|
|
}
|
|
#endif
|
|
PDEBUG(ErrorF("3674 pXGI->VBFlags =%x\n",pXGI->VBFlags)) ;
|
|
|
|
/* Determine CRT1<>CRT2 mode
|
|
* Note: When using VESA or if the bridge is in slavemode, display
|
|
* is ALWAYS in MIRROR_MODE!
|
|
* This requires extra checks in functions using this flag!
|
|
* (see xgi_video.c for example)
|
|
*/
|
|
if(pXGI->VBFlags & DISPTYPE_DISP2)
|
|
{
|
|
if(pXGI->CRT1off)
|
|
{ /* CRT2 only ------------------------------- */
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"CRT1 not detected or forced off. Dual Head mode can't initialize.\n");
|
|
if(pXGIEnt) pXGIEnt->DisableDual = TRUE;
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
pXGI->pInt = NULL;
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
if(pXGI->MergedFBAuto)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr);
|
|
}
|
|
else
|
|
{
|
|
XGIErrorLog(pScrn, mergednocrt1, mergeddisstr);
|
|
}
|
|
if(pXGI->CRT2pScrn) xfree(pXGI->CRT2pScrn);
|
|
pXGI->CRT2pScrn = NULL;
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
#endif
|
|
pXGI->VBFlags |= VB_DISPMODE_SINGLE;
|
|
/* No CRT1? Then we use the video overlay on CRT2 */
|
|
pXGI->XvOnCRT2 = TRUE;
|
|
}
|
|
else /* CRT1 and CRT2 - mirror or dual head ----- */
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGI->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1);
|
|
if(pXGI->VESA != -1)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"VESA option not used in Dual Head mode. VESA disabled.\n");
|
|
}
|
|
if(pXGIEnt) pXGIEnt->DisableDual = FALSE;
|
|
pXGI->VESA = 0;
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
pXGI->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1);
|
|
if(pXGI->VESA != -1)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"VESA option not used in MergedFB mode. VESA disabled.\n");
|
|
}
|
|
pXGI->VESA = 0;
|
|
}
|
|
else
|
|
#endif
|
|
pXGI->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1);
|
|
}
|
|
else
|
|
{ /* CRT1 only ------------------------------- */
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"No CRT2 output selected or no bridge detected. "
|
|
"Dual Head mode can't initialize.\n");
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
pXGI->pInt = NULL;
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
if(pXGI->MergedFBAuto)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr);
|
|
}
|
|
else
|
|
{
|
|
XGIErrorLog(pScrn, mergednocrt2, mergeddisstr);
|
|
}
|
|
if(pXGI->CRT2pScrn) xfree(pXGI->CRT2pScrn);
|
|
pXGI->CRT2pScrn = NULL;
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
#endif
|
|
PDEBUG(ErrorF("3782 pXGI->VBFlags =%x\n",pXGI->VBFlags)) ;
|
|
pXGI->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1);
|
|
}
|
|
|
|
/* Init Ptrs for Save/Restore functions and calc MaxClock */
|
|
XGIDACPreInit(pScrn);
|
|
|
|
/* ********** end of VBFlags setup ********** */
|
|
|
|
/* VBFlags are initialized now. Back them up for SlaveMode modes. */
|
|
pXGI->VBFlags_backup = pXGI->VBFlags;
|
|
|
|
/* Find out about paneldelaycompensation and evaluate option */
|
|
#ifdef XGIDUALHEAD
|
|
if((!pXGI->DualHeadMode) || (!pXGI->SecondHead))
|
|
{
|
|
#endif
|
|
|
|
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* In dual head mode, both heads (currently) share the maxxfbmem equally.
|
|
* If memory sharing is done differently, the following has to be changed;
|
|
* the other modules (eg. accel and Xv) use dhmOffset for hardware
|
|
* pointer settings relative to VideoRAM start and won't need to be changed.
|
|
*/
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->SecondHead == FALSE)
|
|
{
|
|
/* ===== First head (always CRT2) ===== */
|
|
/* We use only half of the memory available */
|
|
pXGI->maxxfbmem /= 2;
|
|
/* Initialize dhmOffset */
|
|
pXGI->dhmOffset = 0;
|
|
/* Copy framebuffer addresses & sizes to entity */
|
|
pXGIEnt->masterFbAddress = pXGI->FbAddress;
|
|
pXGIEnt->masterFbSize = pXGI->maxxfbmem;
|
|
pXGIEnt->slaveFbAddress = pXGI->FbAddress + pXGI->maxxfbmem;
|
|
pXGIEnt->slaveFbSize = pXGI->maxxfbmem;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"%ldKB video RAM at 0x%lx available for master head (CRT2)\n",
|
|
pXGI->maxxfbmem/1024, pXGI->FbAddress);
|
|
}
|
|
else
|
|
{
|
|
/* ===== Second head (always CRT1) ===== */
|
|
/* We use only half of the memory available */
|
|
pXGI->maxxfbmem /= 2;
|
|
/* Adapt FBAddress */
|
|
pXGI->FbAddress += pXGI->maxxfbmem;
|
|
/* Initialize dhmOffset */
|
|
pXGI->dhmOffset = pXGI->availMem - pXGI->maxxfbmem;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"%ldKB video RAM at 0x%lx available for slave head (CRT1)\n",
|
|
pXGI->maxxfbmem/1024, pXGI->FbAddress);
|
|
}
|
|
}
|
|
else
|
|
pXGI->dhmOffset = 0;
|
|
#endif
|
|
|
|
/* Note: Do not use availMem for anything from now. Use
|
|
* maxxfbmem instead. (availMem does not take dual head
|
|
* mode into account.)
|
|
*/
|
|
|
|
pXGI->DRIheapstart = pXGI->maxxfbmem;
|
|
pXGI->DRIheapend = pXGI->availMem;
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGI->DRIheapstart = pXGI->DRIheapend = 0;
|
|
}
|
|
else
|
|
#endif
|
|
if(pXGI->DRIheapstart == pXGI->DRIheapend)
|
|
{
|
|
|
|
pXGI->DRIheapstart = pXGI->DRIheapend = 0;
|
|
}
|
|
#if !defined(__powerpc__)
|
|
/* Now load and initialize VBE module. */
|
|
if(xf86LoadSubModule(pScrn, "vbe"))
|
|
{
|
|
xf86LoaderReqSymLists(vbeSymbols, NULL);
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
pXGI->pVbe = VBEInit(pXGI->pInt,pXGI->pEnt->index);
|
|
#else
|
|
pXGI->pVbe = VBEExtendedInit(pXGI->pInt,pXGI->pEnt->index,
|
|
SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
|
|
#endif
|
|
if(!pXGI->pVbe)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Could not initialize VBE module for DDC\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Could not load VBE module\n");
|
|
}
|
|
|
|
XGIDDCPreInit(pScrn) ;
|
|
#endif
|
|
/* From here, we mainly deal with clocks and modes */
|
|
|
|
/* Set the min pixel clock */
|
|
pXGI->MinClock = 5000;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
|
|
pXGI->MinClock / 1000);
|
|
|
|
from = X_PROBED;
|
|
/*
|
|
* If the user has specified ramdac speed in the XF86Config
|
|
* file, we respect that setting.
|
|
*/
|
|
if(pXGI->pEnt->device->dacSpeeds[0])
|
|
{
|
|
int speed = 0;
|
|
switch(pScrn->bitsPerPixel)
|
|
{
|
|
case 8:
|
|
speed = pXGI->pEnt->device->dacSpeeds[DAC_BPP8];
|
|
break;
|
|
case 16:
|
|
speed = pXGI->pEnt->device->dacSpeeds[DAC_BPP16];
|
|
break;
|
|
case 24:
|
|
speed = pXGI->pEnt->device->dacSpeeds[DAC_BPP24];
|
|
break;
|
|
case 32:
|
|
speed = pXGI->pEnt->device->dacSpeeds[DAC_BPP32];
|
|
break;
|
|
}
|
|
if(speed == 0)
|
|
pXGI->MaxClock = pXGI->pEnt->device->dacSpeeds[0];
|
|
else
|
|
pXGI->MaxClock = speed;
|
|
from = X_CONFIG;
|
|
}
|
|
xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
|
|
pXGI->MaxClock / 1000);
|
|
|
|
/*
|
|
* Setup the ClockRanges, which describe what clock ranges are available,
|
|
* and what sort of modes they can be used for.
|
|
*/
|
|
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
|
|
clockRanges->next = NULL;
|
|
clockRanges->minClock = pXGI->MinClock;
|
|
clockRanges->maxClock = pXGI->MaxClock;
|
|
clockRanges->clockIndex = -1; /* programmable */
|
|
clockRanges->interlaceAllowed = TRUE;
|
|
clockRanges->doubleScanAllowed = TRUE;
|
|
|
|
/*
|
|
* xf86ValidateModes will check that the mode HTotal and VTotal values
|
|
* don't exceed the chipset's limit if pScrn->maxHValue and
|
|
* pScrn->maxVValue are set. Since our XGIValidMode() already takes
|
|
* care of this, we don't worry about setting them here.
|
|
*/
|
|
|
|
/* Select valid modes from those available */
|
|
/*
|
|
* Assuming min pitch 256, min height 128
|
|
*/
|
|
{
|
|
int minpitch, maxpitch, minheight, maxheight;
|
|
minpitch = 256;
|
|
minheight = 128;
|
|
switch(pXGI->VGAEngine)
|
|
{
|
|
case XGI_OLD_VGA:
|
|
maxpitch = 2040;
|
|
maxheight = 2048;
|
|
break;
|
|
default:
|
|
maxpitch = 2048;
|
|
maxheight = 2048;
|
|
break;
|
|
}
|
|
#ifdef XGIMERGED
|
|
pXGI->CheckForCRT2 = FALSE;
|
|
#endif
|
|
XGIDumpMonPtr(pScrn->monitor) ;
|
|
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
|
|
pScrn->display->modes, clockRanges, NULL,
|
|
minpitch, maxpitch,
|
|
pScrn->bitsPerPixel * 8,
|
|
minheight, maxheight,
|
|
pScrn->display->virtualX,
|
|
pScrn->display->virtualY,
|
|
pXGI->maxxfbmem,
|
|
LOOKUP_BEST_REFRESH);
|
|
}
|
|
|
|
if(i == -1)
|
|
{
|
|
XGIErrorLog(pScrn, "xf86ValidateModes() error\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check the virtual screen against the available memory */
|
|
{
|
|
unsigned long memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY;
|
|
|
|
if(memreq > pXGI->maxxfbmem)
|
|
{
|
|
XGIErrorLog(pScrn,
|
|
"Virtual screen too big for memory; %ldK needed, %ldK available\n",
|
|
memreq/1024, pXGI->maxxfbmem/1024);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
pXGI->pInt = NULL;
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Dual Head:
|
|
* -) Go through mode list and mark all those modes as bad,
|
|
* which are unsuitable for dual head mode.
|
|
* -) Find the highest used pixelclock on the master head.
|
|
*/
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
|
|
if(!pXGI->SecondHead)
|
|
{
|
|
|
|
pXGIEnt->maxUsedClock = 0;
|
|
|
|
if((p = first = pScrn->modes))
|
|
{
|
|
do
|
|
{
|
|
n = p->next;
|
|
|
|
/* Modes that require the bridge to operate in SlaveMode
|
|
* are not suitable for Dual Head mode.
|
|
*/
|
|
|
|
/* Search for the highest clock on first head in order to calculate
|
|
* max clock for second head (CRT1)
|
|
*/
|
|
if((p->status == MODE_OK) && (p->Clock > pXGIEnt->maxUsedClock))
|
|
{
|
|
pXGIEnt->maxUsedClock = p->Clock;
|
|
}
|
|
|
|
p = n;
|
|
|
|
}
|
|
while (p != NULL && p != first);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Prune the modes marked as invalid */
|
|
xf86PruneDriverModes(pScrn);
|
|
|
|
if(i == 0 || pScrn->modes == NULL)
|
|
{
|
|
XGIErrorLog(pScrn, "No valid modes found\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
|
|
|
|
/* Set the current mode to the first in the list */
|
|
pScrn->currentMode = pScrn->modes;
|
|
|
|
/* Copy to CurrentLayout */
|
|
pXGI->CurrentLayout.mode = pScrn->currentMode;
|
|
pXGI->CurrentLayout.displayWidth = pScrn->displayWidth;
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1);
|
|
}
|
|
#endif
|
|
|
|
/* Print the list of modes being used */
|
|
xf86PrintModes(pScrn);
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
BOOLEAN acceptcustommodes = TRUE;
|
|
BOOLEAN includelcdmodes = TRUE;
|
|
BOOLEAN isfordvi = FALSE;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2);
|
|
|
|
clockRanges->next = NULL;
|
|
clockRanges->minClock = pXGI->MinClock;
|
|
clockRanges->clockIndex = -1;
|
|
clockRanges->interlaceAllowed = FALSE;
|
|
clockRanges->doubleScanAllowed = FALSE;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n",
|
|
clockRanges->minClock / 1000);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n",
|
|
clockRanges->maxClock / 1000);
|
|
|
|
if((pXGI->XGI_Pr->XGI_VBType & (VB_XGI301|VB_XGI301B|VB_XGI301C|VB_XGI302B)))
|
|
{
|
|
if(!(pXGI->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE;
|
|
if(pXGI->VBFlags & CRT2_LCD) isfordvi = TRUE;
|
|
if(pXGI->VBFlags & CRT2_TV) acceptcustommodes = FALSE;
|
|
}
|
|
else
|
|
{
|
|
includelcdmodes = FALSE;
|
|
acceptcustommodes = FALSE;
|
|
}
|
|
|
|
pXGI->HaveCustomModes2 = FALSE;
|
|
}
|
|
|
|
if(pXGI->MergedFB)
|
|
{
|
|
|
|
pXGI->CheckForCRT2 = TRUE;
|
|
i = xf86ValidateModes(pXGI->CRT2pScrn, pXGI->CRT2pScrn->monitor->Modes,
|
|
pXGI->CRT2pScrn->display->modes, clockRanges,
|
|
NULL, 256, 4088,
|
|
pXGI->CRT2pScrn->bitsPerPixel * 8, 128, 4096,
|
|
pScrn->display->virtualX ? pScrn->virtualX : 0,
|
|
pScrn->display->virtualY ? pScrn->virtualY : 0,
|
|
pXGI->maxxfbmem,
|
|
LOOKUP_BEST_REFRESH);
|
|
pXGI->CheckForCRT2 = FALSE;
|
|
|
|
if(i == -1)
|
|
{
|
|
XGIErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr);
|
|
XGIFreeCRT2Structs(pXGI);
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if(pXGI->MergedFB)
|
|
{
|
|
|
|
if((p = first = pXGI->CRT2pScrn->modes))
|
|
{
|
|
do
|
|
{
|
|
n = p->next;
|
|
p = n;
|
|
}
|
|
while (p != NULL && p != first);
|
|
}
|
|
|
|
xf86PruneDriverModes(pXGI->CRT2pScrn);
|
|
|
|
if(i == 0 || pXGI->CRT2pScrn->modes == NULL)
|
|
{
|
|
XGIErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr);
|
|
XGIFreeCRT2Structs(pXGI);
|
|
pXGI->MergedFB = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if(pXGI->MergedFB)
|
|
{
|
|
|
|
xf86SetCrtcForModes(pXGI->CRT2pScrn, INTERLACE_HALVE_V);
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2);
|
|
|
|
xf86PrintModes(pXGI->CRT2pScrn);
|
|
|
|
pXGI->CRT1Modes = pScrn->modes;
|
|
pXGI->CRT1CurrentMode = pScrn->currentMode;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generating MergedFB mode list\n");
|
|
|
|
pScrn->modes = XGIGenerateModeList(pScrn, pXGI->MetaModes,
|
|
pXGI->CRT1Modes, pXGI->CRT2pScrn->modes,
|
|
pXGI->CRT2Position);
|
|
|
|
if(!pScrn->modes)
|
|
{
|
|
|
|
XGIErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n",
|
|
mergeddisstr);
|
|
XGIFreeCRT2Structs(pXGI);
|
|
pScrn->modes = pXGI->CRT1Modes;
|
|
pXGI->CRT1Modes = NULL;
|
|
pXGI->MergedFB = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(pXGI->MergedFB)
|
|
{
|
|
|
|
/* If no virtual dimension was given by the user,
|
|
* calculate a sane one now. Adapts pScrn->virtualX,
|
|
* pScrn->virtualY and pScrn->displayWidth.
|
|
*/
|
|
XGIRecalcDefaultVirtualSize(pScrn);
|
|
|
|
pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */
|
|
pScrn->currentMode = pScrn->modes;
|
|
|
|
/* Update CurrentLayout */
|
|
pXGI->CurrentLayout.mode = pScrn->currentMode;
|
|
pXGI->CurrentLayout.displayWidth = pScrn->displayWidth;
|
|
|
|
}
|
|
#endif
|
|
|
|
/* Set display resolution */
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
XGIMergedFBSetDpi(pScrn, pXGI->CRT2pScrn, pXGI->CRT2Position);
|
|
}
|
|
else
|
|
#endif
|
|
xf86SetDpi(pScrn, 0, 0);
|
|
|
|
/* Load fb module */
|
|
switch(pScrn->bitsPerPixel)
|
|
{
|
|
case 8:
|
|
case 16:
|
|
case 24:
|
|
case 32:
|
|
if(!xf86LoadSubModule(pScrn, "fb"))
|
|
{
|
|
XGIErrorLog(pScrn, "Failed to load fb module");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
XGIErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel);
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(fbSymbols, NULL);
|
|
|
|
/* Load XAA if needed */
|
|
if(!pXGI->NoAccel)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Accel enabled\n");
|
|
if(!xf86LoadSubModule(pScrn, "xaa"))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not load xaa module\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(xaaSymbols, NULL);
|
|
}
|
|
|
|
/* Load shadowfb if needed */
|
|
if(pXGI->ShadowFB)
|
|
{
|
|
if(!xf86LoadSubModule(pScrn, "shadowfb"))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not load shadowfb module\n");
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGIEnt) pXGIEnt->ErrorAfterFirst = TRUE;
|
|
#endif
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
XGIFreeRec(pScrn);
|
|
return FALSE;
|
|
}
|
|
xf86LoaderReqSymLists(shadowSymbols, NULL);
|
|
}
|
|
|
|
/* Load the dri module if requested. */
|
|
#ifdef XF86DRI
|
|
/*if(pXGI->loadDRI)*/
|
|
{
|
|
if(xf86LoadSubModule(pScrn, "dri"))
|
|
{
|
|
xf86LoaderReqSymLists(driSymbols, drmSymbols, NULL);
|
|
}
|
|
else
|
|
{
|
|
#ifdef XGIDUALHEAD
|
|
if(!pXGI->DualHeadMode)
|
|
#endif
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Remove >Load \"dri\"< from the Module section of your XF86Config file\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Now load and initialize VBE module for VESA and mode restoring. */
|
|
pXGI->UseVESA = 0;
|
|
#if !defined(__powerpc__)
|
|
if(pXGI->VESA == 1)
|
|
{
|
|
if(!pXGI->pVbe)
|
|
{
|
|
if(xf86LoadSubModule(pScrn, "vbe"))
|
|
{
|
|
xf86LoaderReqSymLists(vbeSymbols, NULL);
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
pXGI->pVbe = VBEInit(pXGI->pInt,pXGI->pEnt->index);
|
|
#else
|
|
pXGI->pVbe = VBEExtendedInit(pXGI->pInt,pXGI->pEnt->index,
|
|
SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
|
|
#endif
|
|
}
|
|
}
|
|
if(pXGI->pVbe)
|
|
{
|
|
vbe = VBEGetVBEInfo(pXGI->pVbe);
|
|
pXGI->vesamajor = (unsigned)(vbe->VESAVersion >> 8);
|
|
pXGI->vesaminor = vbe->VESAVersion & 0xff;
|
|
pXGI->vbeInfo = vbe;
|
|
if(pXGI->VESA == 1)
|
|
{
|
|
XGIBuildVesaModeList(pScrn, pXGI->pVbe, vbe);
|
|
VBEFreeVBEInfo(vbe);
|
|
pXGI->UseVESA = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Could not load and initialize VBE module.%s\n",
|
|
(pXGI->VESA == 1) ? " VESA disabled." : "");
|
|
}
|
|
}
|
|
#endif /*#if !defined(__powerpc__) */
|
|
if(pXGI->pVbe)
|
|
{
|
|
vbeFree(pXGI->pVbe);
|
|
pXGI->pVbe = NULL;
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
xf86SetPrimInitDone(pScrn->entityList[0]);
|
|
#endif
|
|
|
|
xgiRestoreExtRegisterLock(pXGI,srlockReg,crlockReg);
|
|
|
|
if(pXGI->pInt) xf86FreeInt10(pXGI->pInt);
|
|
pXGI->pInt = NULL;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_ISDUALHEAD;
|
|
if(pXGI->SecondHead) pXGI->XGI_SD_Flags |= XGI_SD_ISDHSECONDHEAD;
|
|
else pXGI->XGI_SD_Flags &= ~(XGI_SD_SUPPORTXVGAMMA1);
|
|
#ifdef PANORAMIX
|
|
if(!noPanoramiXExtension)
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_ISDHXINERAMA;
|
|
pXGI->XGI_SD_Flags &= ~(XGI_SD_SUPPORTXVGAMMA1);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB) pXGI->XGI_SD_Flags |= XGI_SD_ISMERGEDFB;
|
|
#endif
|
|
|
|
if(pXGI->enablexgictrl) pXGI->XGI_SD_Flags |= XGI_SD_ENABLED;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Map the framebuffer and MMIO memory.
|
|
*/
|
|
|
|
static Bool
|
|
XGIMapMem(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI;
|
|
int mmioFlags;
|
|
|
|
pXGI = XGIPTR(pScrn);
|
|
|
|
/*
|
|
* Map IO registers to virtual address space
|
|
*/
|
|
#if !defined(__alpha__)
|
|
mmioFlags = VIDMEM_MMIO;
|
|
#else
|
|
/*
|
|
* For Alpha, we need to map SPARSE memory, since we need
|
|
* byte/short access.
|
|
*/
|
|
mmioFlags = VIDMEM_MMIO | VIDMEM_SPARSE;
|
|
#endif
|
|
pXGI->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
|
|
pXGI->PciTag, pXGI->IOAddress, 0x10000);
|
|
if (pXGI->IOBase == NULL)
|
|
return FALSE;
|
|
|
|
#ifdef __alpha__
|
|
/*
|
|
* for Alpha, we need to map DENSE memory as well, for
|
|
* setting CPUToScreenColorExpandBase.
|
|
*/
|
|
pXGI->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
|
|
pXGI->PciTag, pXGI->IOAddress, 0x10000);
|
|
|
|
if (pXGI->IOBaseDense == NULL)
|
|
return FALSE;
|
|
#endif /* __alpha__ */
|
|
|
|
pXGI->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
|
|
pXGI->PciTag,
|
|
(unsigned long)pXGI->FbAddress,
|
|
pXGI->FbMapSize);
|
|
|
|
PDEBUG(ErrorF("pXGI->FbBase = 0x%08lx\n",(ULONG)(pXGI->FbBase))) ;
|
|
|
|
if (pXGI->FbBase == NULL)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Unmap the framebuffer and MMIO memory.
|
|
*/
|
|
|
|
static Bool
|
|
XGIUnmapMem(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI;
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = NULL;
|
|
#endif
|
|
|
|
pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
pXGIEnt = pXGI->entityPrivate;
|
|
#endif
|
|
|
|
/* In dual head mode, we must not unmap if the other head still
|
|
* assumes memory as mapped
|
|
*/
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGIEnt->MapCountIOBase)
|
|
{
|
|
pXGIEnt->MapCountIOBase--;
|
|
if((pXGIEnt->MapCountIOBase == 0) || (pXGIEnt->forceUnmapIOBase))
|
|
{
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGIEnt->IOBase, (pXGI->mmioSize * 1024));
|
|
pXGIEnt->IOBase = NULL;
|
|
pXGIEnt->MapCountIOBase = 0;
|
|
pXGIEnt->forceUnmapIOBase = FALSE;
|
|
}
|
|
pXGI->IOBase = NULL;
|
|
}
|
|
#ifdef __alpha__
|
|
if(pXGIEnt->MapCountIOBaseDense)
|
|
{
|
|
pXGIEnt->MapCountIOBaseDense--;
|
|
if((pXGIEnt->MapCountIOBaseDense == 0) || (pXGIEnt->forceUnmapIOBaseDense))
|
|
{
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGIEnt->IOBaseDense, (pXGI->mmioSize * 1024));
|
|
pXGIEnt->IOBaseDense = NULL;
|
|
pXGIEnt->MapCountIOBaseDense = 0;
|
|
pXGIEnt->forceUnmapIOBaseDense = FALSE;
|
|
}
|
|
pXGI->IOBaseDense = NULL;
|
|
}
|
|
#endif /* __alpha__ */
|
|
if(pXGIEnt->MapCountFbBase)
|
|
{
|
|
pXGIEnt->MapCountFbBase--;
|
|
if((pXGIEnt->MapCountFbBase == 0) || (pXGIEnt->forceUnmapFbBase))
|
|
{
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGIEnt->FbBase, pXGI->FbMapSize);
|
|
pXGIEnt->FbBase = NULL;
|
|
pXGIEnt->MapCountFbBase = 0;
|
|
pXGIEnt->forceUnmapFbBase = FALSE;
|
|
|
|
}
|
|
pXGI->FbBase = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGI->IOBase, (pXGI->mmioSize * 1024));
|
|
pXGI->IOBase = NULL;
|
|
#ifdef __alpha__
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGI->IOBaseDense, (pXGI->mmioSize * 1024));
|
|
pXGI->IOBaseDense = NULL;
|
|
#endif
|
|
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pXGI->FbBase, pXGI->FbMapSize);
|
|
pXGI->FbBase = NULL;
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* This function saves the video state.
|
|
*/
|
|
static void
|
|
XGISave(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI;
|
|
vgaRegPtr vgaReg;
|
|
XGIRegPtr xgiReg;
|
|
|
|
PDEBUG(ErrorF("XGISave()\n"));
|
|
|
|
pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* We always save master & slave */
|
|
if(pXGI->DualHeadMode && pXGI->SecondHead) return;
|
|
#endif
|
|
|
|
vgaReg = &VGAHWPTR(pScrn)->SavedReg;
|
|
xgiReg = &pXGI->SavedReg;
|
|
|
|
vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
|
|
|
|
xgiSaveUnlockExtRegisterLock(pXGI,&xgiReg->xgiRegs3C4[0x05],&xgiReg->xgiRegs3D4[0x80]);
|
|
|
|
/* XGISavePrevMode(pScrn) ; */
|
|
|
|
(*pXGI->XGISave)(pScrn, xgiReg);
|
|
|
|
if(pXGI->UseVESA) XGIVESASaveRestore(pScrn, MODE_SAVE);
|
|
|
|
/* "Save" these again as they may have been changed prior to XGISave() call */
|
|
}
|
|
|
|
static void
|
|
XGI_WriteAttr(XGIPtr pXGI, int index, int value)
|
|
{
|
|
(void) inb(pXGI->IODBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
|
|
index |= 0x20;
|
|
outb(pXGI->IODBase + VGA_ATTR_INDEX, index);
|
|
outb(pXGI->IODBase + VGA_ATTR_DATA_W, value);
|
|
}
|
|
|
|
static int
|
|
XGI_ReadAttr(XGIPtr pXGI, int index)
|
|
{
|
|
(void) inb(pXGI->IODBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
|
|
index |= 0x20;
|
|
outb(pXGI->IODBase + VGA_ATTR_INDEX, index);
|
|
return(inb(pXGI->IODBase + VGA_ATTR_DATA_R));
|
|
}
|
|
|
|
#define XGI_FONTS_SIZE (8 * 8192)
|
|
|
|
static void
|
|
XGI_SaveFonts(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
CARD8 *vgaIOBase = (CARD8 *)VGAHWPTR(pScrn)->IOBase;
|
|
#else
|
|
pointer vgaIOBase = VGAHWPTR(pScrn)->Base;
|
|
#endif
|
|
|
|
if(pXGI->fonts) return;
|
|
|
|
/* If in graphics mode, don't save anything */
|
|
attr10 = XGI_ReadAttr(pXGI, 0x10);
|
|
if(attr10 & 0x01) return;
|
|
|
|
if(!(pXGI->fonts = xalloc(XGI_FONTS_SIZE * 2)))
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Could not save console fonts, mem allocation failed\n");
|
|
return;
|
|
}
|
|
|
|
/* save the registers that are needed here */
|
|
miscOut = inXGIREG(XGIMISCR);
|
|
inXGIIDXREG(XGIGR, 0x04, gr4);
|
|
inXGIIDXREG(XGIGR, 0x05, gr5);
|
|
inXGIIDXREG(XGIGR, 0x06, gr6);
|
|
inXGIIDXREG(XGISR, 0x02, seq2);
|
|
inXGIIDXREG(XGISR, 0x04, seq4);
|
|
|
|
/* Force into color mode */
|
|
outXGIREG(XGIMISCW, miscOut | 0x01);
|
|
|
|
inXGIIDXREG(XGISR, 0x01, scrn);
|
|
outXGIIDXREG(XGISR, 0x00, 0x01);
|
|
outXGIIDXREG(XGISR, 0x01, scrn | 0x20);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03);
|
|
|
|
XGI_WriteAttr(pXGI, 0x10, 0x01); /* graphics mode */
|
|
|
|
/*font1 */
|
|
outXGIIDXREG(XGISR, 0x02, 0x04); /* write to plane 2 */
|
|
outXGIIDXREG(XGISR, 0x04, 0x06); /* enable plane graphics */
|
|
outXGIIDXREG(XGIGR, 0x04, 0x02); /* read plane 2 */
|
|
outXGIIDXREG(XGIGR, 0x05, 0x00); /* write mode 0, read mode 0 */
|
|
outXGIIDXREG(XGIGR, 0x06, 0x05); /* set graphics */
|
|
slowbcopy_frombus(vgaIOBase, pXGI->fonts, XGI_FONTS_SIZE);
|
|
|
|
/* font2 */
|
|
outXGIIDXREG(XGISR, 0x02, 0x08); /* write to plane 3 */
|
|
outXGIIDXREG(XGISR, 0x04, 0x06); /* enable plane graphics */
|
|
outXGIIDXREG(XGIGR, 0x04, 0x03); /* read plane 3 */
|
|
outXGIIDXREG(XGIGR, 0x05, 0x00); /* write mode 0, read mode 0 */
|
|
outXGIIDXREG(XGIGR, 0x06, 0x05); /* set graphics */
|
|
slowbcopy_frombus(vgaIOBase, pXGI->fonts + XGI_FONTS_SIZE, XGI_FONTS_SIZE);
|
|
|
|
inXGIIDXREG(XGISR, 0x01, scrn);
|
|
outXGIIDXREG(XGISR, 0x00, 0x01);
|
|
outXGIIDXREG(XGISR, 0x01, scrn & ~0x20);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03);
|
|
|
|
/* Restore clobbered registers */
|
|
XGI_WriteAttr(pXGI, 0x10, attr10);
|
|
outXGIIDXREG(XGISR, 0x02, seq2);
|
|
outXGIIDXREG(XGISR, 0x04, seq4);
|
|
outXGIIDXREG(XGIGR, 0x04, gr4);
|
|
outXGIIDXREG(XGIGR, 0x05, gr5);
|
|
outXGIIDXREG(XGIGR, 0x06, gr6);
|
|
outXGIREG(XGIMISCW, miscOut);
|
|
}
|
|
|
|
static void
|
|
XGI_RestoreFonts(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
CARD8 *vgaIOBase = (CARD8 *)VGAHWPTR(pScrn)->IOBase;
|
|
#else
|
|
pointer vgaIOBase = VGAHWPTR(pScrn)->Base;
|
|
#endif
|
|
|
|
if(!pXGI->fonts) return;
|
|
|
|
/* save the registers that are needed here */
|
|
miscOut = inXGIREG(XGIMISCR);
|
|
attr10 = XGI_ReadAttr(pXGI, 0x10);
|
|
inXGIIDXREG(XGIGR, 0x01, gr1);
|
|
inXGIIDXREG(XGIGR, 0x03, gr3);
|
|
inXGIIDXREG(XGIGR, 0x04, gr4);
|
|
inXGIIDXREG(XGIGR, 0x05, gr5);
|
|
inXGIIDXREG(XGIGR, 0x06, gr6);
|
|
inXGIIDXREG(XGIGR, 0x08, gr8);
|
|
inXGIIDXREG(XGISR, 0x02, seq2);
|
|
inXGIIDXREG(XGISR, 0x04, seq4);
|
|
|
|
/* Force into color mode */
|
|
outXGIREG(XGIMISCW, miscOut | 0x01);
|
|
inXGIIDXREG(XGISR, 0x01, scrn);
|
|
outXGIIDXREG(XGISR, 0x00, 0x01);
|
|
outXGIIDXREG(XGISR, 0x01, scrn | 0x20);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03);
|
|
|
|
XGI_WriteAttr(pXGI, 0x10, 0x01); /* graphics mode */
|
|
if(pScrn->depth == 4)
|
|
{
|
|
outXGIIDXREG(XGIGR, 0x03, 0x00); /* don't rotate, write unmodified */
|
|
outXGIIDXREG(XGIGR, 0x08, 0xFF); /* write all bits in a byte */
|
|
outXGIIDXREG(XGIGR, 0x01, 0x00); /* all planes come from CPU */
|
|
}
|
|
|
|
outXGIIDXREG(XGISR, 0x02, 0x04); /* write to plane 2 */
|
|
outXGIIDXREG(XGISR, 0x04, 0x06); /* enable plane graphics */
|
|
outXGIIDXREG(XGIGR, 0x04, 0x02); /* read plane 2 */
|
|
outXGIIDXREG(XGIGR, 0x05, 0x00); /* write mode 0, read mode 0 */
|
|
outXGIIDXREG(XGIGR, 0x06, 0x05); /* set graphics */
|
|
slowbcopy_tobus(pXGI->fonts, vgaIOBase, XGI_FONTS_SIZE);
|
|
|
|
outXGIIDXREG(XGISR, 0x02, 0x08); /* write to plane 3 */
|
|
outXGIIDXREG(XGISR, 0x04, 0x06); /* enable plane graphics */
|
|
outXGIIDXREG(XGIGR, 0x04, 0x03); /* read plane 3 */
|
|
outXGIIDXREG(XGIGR, 0x05, 0x00); /* write mode 0, read mode 0 */
|
|
outXGIIDXREG(XGIGR, 0x06, 0x05); /* set graphics */
|
|
slowbcopy_tobus(pXGI->fonts + XGI_FONTS_SIZE, vgaIOBase, XGI_FONTS_SIZE);
|
|
|
|
inXGIIDXREG(XGISR, 0x01, scrn);
|
|
outXGIIDXREG(XGISR, 0x00, 0x01);
|
|
outXGIIDXREG(XGISR, 0x01, scrn & ~0x20);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03);
|
|
|
|
/* restore the registers that were changed */
|
|
outXGIREG(XGIMISCW, miscOut);
|
|
XGI_WriteAttr(pXGI, 0x10, attr10);
|
|
outXGIIDXREG(XGIGR, 0x01, gr1);
|
|
outXGIIDXREG(XGIGR, 0x03, gr3);
|
|
outXGIIDXREG(XGIGR, 0x04, gr4);
|
|
outXGIIDXREG(XGIGR, 0x05, gr5);
|
|
outXGIIDXREG(XGIGR, 0x06, gr6);
|
|
outXGIIDXREG(XGIGR, 0x08, gr8);
|
|
outXGIIDXREG(XGISR, 0x02, seq2);
|
|
outXGIIDXREG(XGISR, 0x04, seq4);
|
|
}
|
|
|
|
#undef XGI_FONTS_SIZE
|
|
|
|
/* VESASaveRestore taken from vesa driver */
|
|
static void
|
|
XGIVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
/* Query amount of memory to save state */
|
|
if((function == MODE_QUERY) ||
|
|
(function == MODE_SAVE && pXGI->state == NULL))
|
|
{
|
|
|
|
/* Make sure we save at least this information in case of failure */
|
|
(void)VBEGetVBEMode(pXGI->pVbe, &pXGI->stateMode);
|
|
XGI_SaveFonts(pScrn);
|
|
|
|
if(pXGI->vesamajor > 1)
|
|
{
|
|
if(!VBESaveRestore(pXGI->pVbe, function, (pointer)&pXGI->state,
|
|
&pXGI->stateSize, &pXGI->statePage))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Save/Restore Super VGA state */
|
|
if(function != MODE_QUERY)
|
|
{
|
|
|
|
if(pXGI->vesamajor > 1)
|
|
{
|
|
if(function == MODE_RESTORE)
|
|
{
|
|
memcpy(pXGI->state, pXGI->pstate, pXGI->stateSize);
|
|
}
|
|
|
|
if(VBESaveRestore(pXGI->pVbe,function,(pointer)&pXGI->state,
|
|
&pXGI->stateSize,&pXGI->statePage) &&
|
|
(function == MODE_SAVE))
|
|
{
|
|
/* don't rely on the memory not being touched */
|
|
if(!pXGI->pstate)
|
|
{
|
|
pXGI->pstate = xalloc(pXGI->stateSize);
|
|
}
|
|
memcpy(pXGI->pstate, pXGI->state, pXGI->stateSize);
|
|
}
|
|
}
|
|
|
|
if(function == MODE_RESTORE)
|
|
{
|
|
VBESetVBEMode(pXGI->pVbe, pXGI->stateMode, NULL);
|
|
XGI_RestoreFonts(pScrn);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialise a new mode. This is currently done using the
|
|
* "initialise struct, restore/write struct to HW" model for
|
|
* the old chipsets (5597/530/6326). For newer chipsets,
|
|
* we use our own mode switching code (or VESA).
|
|
*/
|
|
|
|
static Bool
|
|
XGIModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
vgaRegPtr vgaReg;
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
XGIRegPtr xgiReg;
|
|
unsigned char tmpval;
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = NULL;
|
|
#endif
|
|
|
|
/* PDEBUG(ErrorF("XGIModeInit(). \n"));*/
|
|
PDEBUG(ErrorF("XGIModeInit Resolution (%d, %d) \n", mode->HDisplay, mode->VDisplay));
|
|
PDEBUG(ErrorF("XGIModeInit VVRefresh (%8.3f) \n", mode->VRefresh));
|
|
PDEBUG(ErrorF("XGIModeInit Color Depth (%d) \n", pScrn->depth));
|
|
|
|
/* Jong Lin 08-26-2005; save current mode */
|
|
CurrentHDisplay=mode->HDisplay;
|
|
CurrentVDisplay=mode->VDisplay;
|
|
CurrentColorDepth=pScrn->depth;
|
|
|
|
andXGIIDXREG(XGICR,0x11,0x7f); /* Unlock CRTC registers */
|
|
|
|
XGIModifyModeInfo(mode); /* Quick check of the mode parameters */
|
|
|
|
if(pXGI->UseVESA)
|
|
{ /* With VESA: */
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* No dual head mode when using VESA */
|
|
if(pXGI->SecondHead)
|
|
{
|
|
return TRUE;
|
|
}
|
|
/* if(pXGI->SecondHead) */
|
|
#endif
|
|
|
|
PDEBUG(ErrorF("XGIModeInit() VESA. \n"));
|
|
pScrn->vtSema = TRUE;
|
|
|
|
/*
|
|
* This order is required:
|
|
* The video bridge needs to be adjusted before the
|
|
* BIOS is run as the BIOS sets up CRT2 according to
|
|
* these register settings.
|
|
* After the BIOS is run, the bridges and turboqueue
|
|
* registers need to be readjusted as th e BIOSmay
|
|
* very probably have messed them up.
|
|
*/
|
|
|
|
if(!XGISetVESAMode(pScrn, mode))
|
|
{
|
|
XGIErrorLog(pScrn, "XGISetVESAMode() failed\n");
|
|
return FALSE;
|
|
}
|
|
xgiSaveUnlockExtRegisterLock(pXGI,NULL,NULL);
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"REAL REGISTER CONTENTS AFTER SETMODE:\n");
|
|
#endif
|
|
if(!(*pXGI->ModeInit)(pScrn, mode))
|
|
{
|
|
XGIErrorLog(pScrn, "ModeInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
vgaHWProtect(pScrn, TRUE);
|
|
(*pXGI->XGIRestore)(pScrn, &pXGI->ModeReg);
|
|
vgaHWProtect(pScrn, FALSE);
|
|
|
|
}
|
|
else
|
|
{ /* Without VESA: */
|
|
|
|
PDEBUG(ErrorF("XGIModeInit(). none VESA\n"));
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
|
|
if(!(*pXGI->ModeInit)(pScrn, mode))
|
|
{
|
|
XGIErrorLog(pScrn, "ModeInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
pScrn->vtSema = TRUE;
|
|
|
|
pXGIEnt = pXGI->entityPrivate;
|
|
|
|
/* Head 2 (slave) is always CRT1 */
|
|
XGIPreSetMode(pScrn, mode, XGI_MODE_CRT1);
|
|
if(!XGIBIOSSetModeCRT1(pXGI->XGI_Pr, &pXGI->xgi_HwDevExt, pScrn, mode, pXGI->IsCustom))
|
|
{
|
|
XGIErrorLog(pScrn, "XGIBIOSSetModeCRT1() failed\n");
|
|
return FALSE;
|
|
}
|
|
XGIPostSetMode(pScrn, &pXGI->ModeReg);
|
|
XGIAdjustFrame(pXGIEnt->pScrn_1->scrnIndex,
|
|
pXGIEnt->pScrn_1->frameX0,
|
|
pXGIEnt->pScrn_1->frameY0, 0);
|
|
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* For other chipsets, use the old method */
|
|
|
|
/* Initialise the ModeReg values */
|
|
if(!vgaHWInit(pScrn, mode))
|
|
{
|
|
XGIErrorLog(pScrn, "vgaHWInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Reset our PIOOffset as vgaHWInit might have reset it */
|
|
VGAHWPTR(pScrn)->PIOOffset = pXGI->IODBase + (pXGI->PciInfo->ioBase[2] & 0xFFFC) - 0x380;
|
|
|
|
/* Prepare the register contents */
|
|
if(!(*pXGI->ModeInit)(pScrn, mode))
|
|
{
|
|
XGIErrorLog(pScrn, "ModeInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
pScrn->vtSema = TRUE;
|
|
|
|
/* Program the registers */
|
|
vgaHWProtect(pScrn, TRUE);
|
|
vgaReg = &hwp->ModeReg;
|
|
xgiReg = &pXGI->ModeReg;
|
|
|
|
vgaReg->Attribute[0x10] = 0x01;
|
|
if(pScrn->bitsPerPixel > 8)
|
|
{
|
|
vgaReg->Graphics[0x05] = 0x00;
|
|
}
|
|
|
|
vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
|
|
|
|
(*pXGI->XGIRestore)(pScrn, xgiReg);
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"REAL REGISTER CONTENTS AFTER SETMODE:\n");
|
|
(*pXGI->ModeInit)(pScrn, mode);
|
|
#endif
|
|
|
|
vgaHWProtect(pScrn, FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
if(pXGI->Chipset == PCI_CHIP_XGIXG40 ||
|
|
pXGI->Chipset == PCI_CHIP_XGIXG20)
|
|
{
|
|
/* PDEBUG(XGIDumpRegs(pScrn)) ; */
|
|
PDEBUG(ErrorF(" *** PreSetMode(). \n"));
|
|
XGIPreSetMode(pScrn, mode, XGI_MODE_SIMU);
|
|
/* PDEBUG(XGIDumpRegs(pScrn)) ; */
|
|
PDEBUG(ErrorF(" *** Start SetMode() \n"));
|
|
|
|
if(!XGIBIOSSetMode(pXGI->XGI_Pr, &pXGI->xgi_HwDevExt, pScrn,
|
|
mode, pXGI->IsCustom, TRUE))
|
|
{
|
|
XGIErrorLog(pScrn, "XGIBIOSSetModeCRT() failed\n");
|
|
return FALSE;
|
|
}
|
|
Volari_EnableAccelerator(pScrn);
|
|
/* XGIPostSetMode(pScrn, &pXGI->ModeReg); */
|
|
/* outXGIIDXREG(XGISR, 0x20, 0xA1) ; */
|
|
/* outXGIIDXREG(XGISR, 0x1E, 0xDA) ; */
|
|
/* PDEBUG(XGIDumpRegs(pScrn)) ; */
|
|
}
|
|
|
|
/* Update Currentlayout */
|
|
pXGI->CurrentLayout.mode = mode;
|
|
|
|
#ifdef __powerpc__
|
|
inXGIIDXREG(XGICR, 0x4D, tmpval);
|
|
if(pScrn->depth == 16)
|
|
tmpval = (tmpval & 0xE0) | 0x0B; //word swap
|
|
else if(pScrn->depth == 24)
|
|
tmpval = (tmpval & 0xE0) | 0x15; //dword swap
|
|
else
|
|
tmpval = tmpval & 0xE0 ; // no swap
|
|
|
|
outXGIIDXREG(XGICR, 0x4D, tmpval);
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
XGISetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
|
|
{
|
|
XGIPtr pXGI;
|
|
int mode;
|
|
|
|
pXGI = XGIPTR(pScrn);
|
|
|
|
if(!(mode = XGICalcVESAModeIndex(pScrn, pMode))) return FALSE;
|
|
|
|
mode |= (1 << 15); /* Don't clear framebuffer */
|
|
mode |= (1 << 14); /* Use linear adressing */
|
|
|
|
if(VBESetVBEMode(pXGI->pVbe, mode, NULL) == FALSE)
|
|
{
|
|
XGIErrorLog(pScrn, "Setting VESA mode 0x%x failed\n",
|
|
mode & 0x0fff);
|
|
return (FALSE);
|
|
}
|
|
|
|
if(pMode->HDisplay != pScrn->virtualX)
|
|
{
|
|
VBESetLogicalScanline(pXGI->pVbe, pScrn->virtualX);
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Setting VESA mode 0x%x succeeded\n",
|
|
mode & 0x0fff);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/* static void
|
|
XGISpecialRestore(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
XGIRegPtr xgiReg = &pXGI->SavedReg;
|
|
unsigned char temp;
|
|
int i;
|
|
|
|
if(!(pXGI->ChipFlags & XGICF_Is65x)) return;
|
|
inXGIIDXREG(XGICR, 0x34, temp);
|
|
temp &= 0x7f;
|
|
if(temp > 0x13) return;
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL,NULL);
|
|
#endif
|
|
|
|
outXGIIDXREG(XGICAP, 0x3f, xgiReg->xgiCapt[0x3f]);
|
|
outXGIIDXREG(XGICAP, 0x00, xgiReg->xgiCapt[0x00]);
|
|
for(i = 0; i < 0x4f; i++)
|
|
{
|
|
outXGIIDXREG(XGICAP, i, xgiReg->xgiCapt[i]);
|
|
}
|
|
outXGIIDXREG(XGIVID, 0x32, (xgiReg->xgiVid[0x32] & ~0x05));
|
|
outXGIIDXREG(XGIVID, 0x30, xgiReg->xgiVid[0x30]);
|
|
outXGIIDXREG(XGIVID, 0x32, ((xgiReg->xgiVid[0x32] & ~0x04) | 0x01));
|
|
outXGIIDXREG(XGIVID, 0x30, xgiReg->xgiVid[0x30]);
|
|
|
|
if(!(pXGI->ChipFlags & XGICF_Is651)) return;
|
|
if(!(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB)) return;
|
|
|
|
inXGIIDXREG(XGICR, 0x30, temp);
|
|
if(temp & 0x40)
|
|
{
|
|
unsigned char myregs[] =
|
|
{
|
|
0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c,
|
|
0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10,
|
|
0x11, 0x04, 0x05, 0x06, 0x07, 0x00,
|
|
0x2e
|
|
};
|
|
for(i = 0; i <= 18; i++)
|
|
{
|
|
outXGIIDXREG(XGIPART1, myregs[i], xgiReg->VBPart1[myregs[i]]);
|
|
}
|
|
}
|
|
else if((temp & 0x20) || (temp & 0x9c))
|
|
{
|
|
unsigned char myregs[] =
|
|
{
|
|
0x04, 0x05, 0x06, 0x07, 0x00, 0x2e
|
|
};
|
|
for(i = 0; i <= 5; i++)
|
|
{
|
|
outXGIIDXREG(XGIPART1, myregs[i], xgiReg->VBPart1[myregs[i]]);
|
|
}
|
|
}
|
|
} */
|
|
|
|
static void
|
|
XGISavePrevMode(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef SAVE_RESTORE_PREVIOUS_MODE
|
|
#if !defined(__powerpc__)
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
xf86Int10InfoPtr pInt = NULL ; /* Our int10 */
|
|
|
|
if(xf86LoadSubModule(pScrn, "int10"))
|
|
{
|
|
pInt = xf86InitInt10(pXGI->pEnt->index);
|
|
pXGI->SavedMode = -1 ;
|
|
|
|
if(pInt)
|
|
{
|
|
|
|
int i,j ;
|
|
|
|
for( i=0,j = 0x30 ; j <= 0x38 ; j++ , i++)
|
|
{
|
|
inXGIIDXREG(XGICR,j,pXGI->ScratchSet[i]);
|
|
PDEBUG2(ErrorF("Saved Scratch[%d] = %02X\n",i,pXGI->ScratchSet[i])) ;
|
|
}
|
|
|
|
pInt->num = 0x10 ;
|
|
pInt->ax = 0xF00 ; /* Get current Mode */
|
|
xf86ExecX86int10(pInt) ;
|
|
|
|
pXGI->SavedMode = pInt->ax & 0x7f ;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"XGISavePrevMode(): saved previous mode = 0x%x.\n",
|
|
pXGI->SavedMode);
|
|
xf86FreeInt10(pInt) ;
|
|
pInt = NULL ;
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGISavePrevMode(): pInt is NULL, cannot save previous mode.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGISavePrevMode(): Load int10 module fail, cannot save previous mode.\n");
|
|
}
|
|
|
|
#endif /* if !defined(__powerpc__) */
|
|
#endif /* SAVE_RESTORE_PREVIOUS_MODE */
|
|
}
|
|
|
|
static void
|
|
XGIRestorePrevMode(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef SAVE_RESTORE_PREVIOUS_MODE
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
xf86Int10InfoPtr pInt = NULL ; /* Our int10 */
|
|
#if !defined(__powerpc__)
|
|
PDEBUG(ErrorF("XGIRestorePrevMode()\n")) ;
|
|
if( pXGI->SavedMode == -1 )
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIRestorePrevMode(): no previous saved mode, ignore restoring.\n");
|
|
return ;
|
|
}
|
|
|
|
|
|
if(xf86LoadSubModule(pScrn, "int10"))
|
|
{
|
|
pInt = xf86InitInt10(pXGI->pEnt->index);
|
|
|
|
if(pInt)
|
|
{
|
|
int i,j ;
|
|
for( i=0,j = 0x30 ; j <= 0x38 ; j++ , i++)
|
|
{
|
|
outXGIIDXREG(XGICR,j,pXGI->ScratchSet[i]);
|
|
PDEBUG2(ErrorF("Restored Scratch[%d] = %02X\n",i,pXGI->ScratchSet[i])) ;
|
|
}
|
|
pInt->num = 0x10 ;
|
|
pInt->ax = 0x80 | pXGI->SavedMode ;
|
|
/* ah = 0 , set mode */
|
|
xf86ExecX86int10(pInt) ;
|
|
|
|
xf86FreeInt10(pInt) ;
|
|
pInt = NULL ;
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIRestorePrevMode(): pInt is NULL, cannot restore previous mode.\n");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"XGIRestorePrevMode(): Load int10 module fail, cannot restore previous mode.\n");
|
|
}
|
|
#endif /* if !defined(__powerpc__)*/
|
|
#endif /* SAVE_RESTORE_PREVIOUS_MODE */
|
|
}
|
|
|
|
/*
|
|
* Restore the initial mode. To be used internally only!
|
|
*/
|
|
static void
|
|
XGIRestore(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
XGIRegPtr xgiReg = &pXGI->SavedReg;
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
vgaRegPtr vgaReg = &hwp->SavedReg;
|
|
/* Bool doit = FALSE, doitlater = FALSE;
|
|
Bool vesasuccess = FALSE; */
|
|
|
|
/* WARNING: Don't ever touch this. It now seems to work on
|
|
* all chipset/bridge combinations - but finding out the
|
|
* correct combination was pure hell.
|
|
*/
|
|
|
|
/* Wait for the accelerators */
|
|
PDEBUG(ErrorF("XGIRestore():\n")) ;
|
|
if(pXGI->AccelInfoPtr)
|
|
{
|
|
(*pXGI->AccelInfoPtr->Sync)(pScrn);
|
|
}
|
|
|
|
vgaHWProtect(pScrn, TRUE);
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL,NULL);
|
|
#endif
|
|
|
|
(*pXGI->XGIRestore)(pScrn, xgiReg);
|
|
/* XGIRestorePrevMode(pScrn) ; */
|
|
|
|
vgaHWProtect(pScrn, TRUE);
|
|
if(pXGI->Primary)
|
|
{
|
|
vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
|
|
}
|
|
|
|
/* Restore TV. This is rather complicated, but if we don't do it,
|
|
* TV output will flicker terribly
|
|
*/
|
|
|
|
|
|
xgiRestoreExtRegisterLock(pXGI,xgiReg->xgiRegs3C4[5],xgiReg->xgiRegs3D4[0x80]);
|
|
|
|
vgaHWProtect(pScrn, FALSE);
|
|
}
|
|
|
|
static void
|
|
XGIVESARestore(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
if(pXGI->UseVESA)
|
|
{
|
|
XGIVESASaveRestore(pScrn, MODE_RESTORE);
|
|
#ifdef XGIVRAMQ
|
|
/* Restore queue mode registers on 315/330 series */
|
|
/* (This became necessary due to the switch to VRAM queue) */
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* Restore bridge config registers - to be called BEFORE VESARestore */
|
|
static void
|
|
XGIBridgeRestore(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* We only restore for master head */
|
|
if(pXGI->DualHeadMode && pXGI->SecondHead) return;
|
|
#endif
|
|
|
|
}
|
|
|
|
/* Our generic BlockHandler for Xv */
|
|
static void
|
|
XGIBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
|
|
{
|
|
ScreenPtr pScreen = screenInfo.screens[i];
|
|
ScrnInfoPtr pScrn = xf86Screens[i];
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
pScreen->BlockHandler = pXGI->BlockHandler;
|
|
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
|
|
pScreen->BlockHandler = XGIBlockHandler;
|
|
|
|
if(pXGI->VideoTimerCallback)
|
|
{
|
|
(*pXGI->VideoTimerCallback)(pScrn, currentTime.milliseconds);
|
|
}
|
|
|
|
if(pXGI->RenderCallback)
|
|
{
|
|
(*pXGI->RenderCallback)(pScrn);
|
|
}
|
|
}
|
|
|
|
/* Mandatory
|
|
* This gets called at the start of each server generation
|
|
*
|
|
* We use pScrn and not CurrentLayout here, because the
|
|
* properties we use have not changed (displayWidth,
|
|
* depth, bitsPerPixel)
|
|
*/
|
|
static Bool
|
|
XGIScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
|
|
{
|
|
ScrnInfoPtr pScrn;
|
|
vgaHWPtr hwp;
|
|
XGIPtr pXGI;
|
|
int ret;
|
|
VisualPtr visual;
|
|
unsigned long OnScreenSize;
|
|
int height, width, displayWidth;
|
|
unsigned char *FBStart;
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = NULL;
|
|
#endif
|
|
DumpDDIName("XGIScreenInit\n") ;
|
|
pScrn = xf86Screens[pScreen->myNum];
|
|
|
|
hwp = VGAHWPTR(pScrn);
|
|
|
|
pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if((!pXGI->DualHeadMode) || (!pXGI->SecondHead))
|
|
{
|
|
#endif
|
|
#if !defined(__powerpc__)
|
|
if(xf86LoadSubModule(pScrn, "vbe"))
|
|
{
|
|
xf86LoaderReqSymLists(vbeSymbols, NULL);
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
|
|
pXGI->pVbe = VBEInit(NULL, pXGI->pEnt->index);
|
|
#else
|
|
pXGI->pVbe = VBEExtendedInit(NULL, pXGI->pEnt->index,
|
|
SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
XGIErrorLog(pScrn, "Failed to load VBE submodule\n");
|
|
}
|
|
#endif /* if !defined(__powerpc__) */
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGIEnt = pXGI->entityPrivate;
|
|
pXGIEnt->refCount++;
|
|
}
|
|
#endif
|
|
|
|
/* Map the VGA memory and get the VGA IO base */
|
|
if(pXGI->Primary)
|
|
{
|
|
hwp->MapSize = 0x10000; /* Standard 64k VGA window */
|
|
if(!vgaHWMapMem(pScrn))
|
|
{
|
|
XGIErrorLog(pScrn, "Could not map VGA memory window\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
vgaHWGetIOBase(hwp);
|
|
|
|
/* Patch the PIOOffset inside vgaHW to use
|
|
* our relocated IO ports.
|
|
*/
|
|
VGAHWPTR(pScrn)->PIOOffset = pXGI->IODBase + (pXGI->PciInfo->ioBase[2] & 0xFFFC) - 0x380;
|
|
|
|
/* Map the XGI memory and MMIO areas */
|
|
if(!XGIMapMem(pScrn))
|
|
{
|
|
XGIErrorLog(pScrn, "XGIMapMem() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
#endif
|
|
|
|
/* Enable TurboQueue so that XGISave() saves it in enabled
|
|
* state. If we don't do this, X will hang after a restart!
|
|
* (Happens for some unknown reason only when using VESA
|
|
* for mode switching; assumingly a BIOS issue.)
|
|
* This is done on 300 and 315 series only.
|
|
*/
|
|
if(pXGI->UseVESA)
|
|
{
|
|
#ifdef XGIVRAMQ
|
|
if(pXGI->VGAEngine != XGI_315_VGA)
|
|
#endif
|
|
XGIEnableTurboQueue(pScrn);
|
|
|
|
}
|
|
|
|
/* Save the current state */
|
|
XGISave(pScrn);
|
|
|
|
/* XGI_InitHwDevInfo(pScrn); */
|
|
|
|
PDEBUG(ErrorF("--- ScreenInit --- \n")) ;
|
|
PDEBUG(XGIDumpRegs(pScrn)) ;
|
|
|
|
/* Initialise the first mode */
|
|
if(!XGIModeInit(pScrn, pScrn->currentMode))
|
|
{
|
|
XGIErrorLog(pScrn, "XGIModeInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
PDEBUG(ErrorF("--- XGIModeInit --- \n")) ;
|
|
PDEBUG(XGIDumpRegs(pScrn)) ;
|
|
|
|
/* Darken the screen for aesthetic reasons */
|
|
/* Not using Dual Head variant on purpose; we darken
|
|
* the screen for both displays, and un-darken
|
|
* it when the second head is finished
|
|
*/
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_ON);
|
|
|
|
/* Set the viewport */
|
|
XGIAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
|
|
|
|
/*
|
|
* The next step is to setup the screen's visuals, and initialise the
|
|
* framebuffer code. In cases where the framebuffer's default
|
|
* choices for things like visual layouts and bits per RGB are OK,
|
|
* this may be as simple as calling the framebuffer's ScreenInit()
|
|
* function. If not, the visuals will need to be setup before calling
|
|
* a fb ScreenInit() function and fixed up after.
|
|
*
|
|
* For most PC hardware at depths >= 8, the defaults that cfb uses
|
|
* are not appropriate. In this driver, we fixup the visuals after.
|
|
*/
|
|
|
|
/*
|
|
* Reset visual list.
|
|
*/
|
|
miClearVisualTypes();
|
|
|
|
/* Setup the visuals we support. */
|
|
|
|
/*
|
|
* For bpp > 8, the default visuals are not acceptable because we only
|
|
* support TrueColor and not DirectColor.
|
|
*/
|
|
if(!miSetVisualTypes(pScrn->depth,
|
|
(pScrn->bitsPerPixel > 8) ?
|
|
TrueColorMask : miGetDefaultVisualMask(pScrn->depth),
|
|
pScrn->rgbBits, pScrn->defaultVisual))
|
|
{
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
XGIErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n",
|
|
pScrn->bitsPerPixel);
|
|
return FALSE;
|
|
}
|
|
|
|
width = pScrn->virtualX;
|
|
height = pScrn->virtualY;
|
|
displayWidth = pScrn->displayWidth;
|
|
|
|
if(pXGI->Rotate)
|
|
{
|
|
height = pScrn->virtualX;
|
|
width = pScrn->virtualY;
|
|
}
|
|
|
|
if(pXGI->ShadowFB)
|
|
{
|
|
pXGI->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
|
|
pXGI->ShadowPtr = xalloc(pXGI->ShadowPitch * height);
|
|
displayWidth = pXGI->ShadowPitch / (pScrn->bitsPerPixel >> 3);
|
|
FBStart = pXGI->ShadowPtr;
|
|
}
|
|
else
|
|
{
|
|
pXGI->ShadowPtr = NULL;
|
|
FBStart = pXGI->FbBase;
|
|
}
|
|
|
|
if(!miSetPixmapDepths())
|
|
{
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
XGIErrorLog(pScrn, "miSetPixmapDepths() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Point cmdQueuePtr to pXGIEnt for shared usage
|
|
* (same technique is then eventually used in DRIScreeninit)
|
|
* For 315/330 series, this is done in EnableTurboQueue
|
|
* which has already been called during ModeInit().
|
|
*/
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->SecondHead)
|
|
pXGI->cmdQueueLenPtr = &(XGIPTR(pXGIEnt->pScrn_1)->cmdQueueLen);
|
|
else
|
|
#endif
|
|
pXGI->cmdQueueLenPtr = &(pXGI->cmdQueueLen);
|
|
|
|
pXGI->cmdQueueLen = 0; /* Force an EngineIdle() at start */
|
|
|
|
#ifdef XF86DRI
|
|
/*if(pXGI->loadDRI)*/
|
|
{
|
|
#ifdef XGIDUALHEAD
|
|
/* No DRI in dual head mode */
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGI->directRenderingEnabled = FALSE;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"DRI not supported in Dual Head mode\n");
|
|
}
|
|
else
|
|
#endif
|
|
/* Force the initialization of the context */
|
|
/* if(pXGI->VGAEngine != XGI_315_VGA) { */
|
|
if( (FbDevExist) && (pXGI->Chipset != PCI_CHIP_XGIXG20) )
|
|
{
|
|
pXGI->directRenderingEnabled = XGIDRIScreenInit(pScreen);
|
|
PDEBUG(ErrorF("--- DRI supported \n"));
|
|
}
|
|
else
|
|
{
|
|
PDEBUG(ErrorF("--- DRI not supported \n"));
|
|
xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED,
|
|
"DRI not supported on this chipset\n");
|
|
pXGI->directRenderingEnabled = FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Call the framebuffer layer's ScreenInit function, and fill in other
|
|
* pScreen fields.
|
|
*/
|
|
switch(pScrn->bitsPerPixel)
|
|
{
|
|
case 24:
|
|
case 8:
|
|
case 16:
|
|
case 32:
|
|
ret = fbScreenInit(pScreen, FBStart, width,
|
|
height, pScrn->xDpi, pScrn->yDpi,
|
|
displayWidth, pScrn->bitsPerPixel);
|
|
break;
|
|
default:
|
|
ret = FALSE;
|
|
break;
|
|
}
|
|
if(!ret)
|
|
{
|
|
XGIErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n",
|
|
pScrn->bitsPerPixel);
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Initialize RENDER ext; must be after RGB ordering fixed */
|
|
fbPictureInit(pScreen, 0, 0);
|
|
|
|
/* hardware cursor needs to wrap this layer <-- TW: what does that mean? */
|
|
if(!pXGI->ShadowFB) XGIDGAInit(pScreen);
|
|
|
|
xf86SetBlackWhitePixels(pScreen);
|
|
|
|
if(!pXGI->NoAccel)
|
|
{
|
|
switch(pXGI->VGAEngine)
|
|
{
|
|
case XGI_XGX_VGA:
|
|
/* Volari_EnableAccelerator(pScrn); */
|
|
PDEBUG(ErrorF("---Volari Accel.. \n"));
|
|
default:
|
|
Volari_AccelInit(pScreen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
PDEBUG(ErrorF("--- AccelInit --- \n")) ;
|
|
PDEBUG(XGIDumpRegs(pScrn)) ;
|
|
|
|
miInitializeBackingStore(pScreen);
|
|
xf86SetBackingStore(pScreen);
|
|
xf86SetSilkenMouse(pScreen);
|
|
|
|
/* Initialise cursor functions */
|
|
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
|
|
|
|
if(pXGI->HWCursor)
|
|
{
|
|
XGIHWCursorInit(pScreen);
|
|
}
|
|
|
|
/* Initialise default colourmap */
|
|
if(!miCreateDefColormap(pScreen))
|
|
{
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
XGIErrorLog(pScrn, "miCreateDefColormap() failed\n");
|
|
return FALSE;
|
|
}
|
|
if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits,
|
|
XGILoadPalette, NULL,
|
|
CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH))
|
|
{
|
|
PDEBUG(ErrorF("XGILoadPalette() check-return. \n"));
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
XGIErrorLog(pScrn, "xf86HandleColormaps() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
if (!xf86HandleColormaps(pScreen, 256, 8, XGILoadPalette, NULL,
|
|
CMAP_RELOAD_ON_MODE_SWITCH))
|
|
{
|
|
return FALSE;
|
|
}
|
|
*/
|
|
xf86DPMSInit(pScreen, (DPMSSetProcPtr)XGIDisplayPowerManagementSet, 0);
|
|
|
|
/* Init memPhysBase and fbOffset in pScrn */
|
|
pScrn->memPhysBase = pXGI->FbAddress;
|
|
pScrn->fbOffset = 0;
|
|
|
|
pXGI->ResetXv = pXGI->ResetXvGamma = NULL;
|
|
|
|
#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension))
|
|
if(!pXGI->NoXvideo)
|
|
{
|
|
XGIInitVideo(pScreen);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XF86DRI
|
|
/*if(pXGI->loadDRI)*/
|
|
{
|
|
if(pXGI->directRenderingEnabled)
|
|
{
|
|
/* Now that mi, drm and others have done their thing,
|
|
* complete the DRI setup.
|
|
*/
|
|
pXGI->directRenderingEnabled = XGIDRIFinishScreenInit(pScreen);
|
|
}
|
|
if(pXGI->directRenderingEnabled)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
|
|
/* TODO */
|
|
/* XGISetLFBConfig(pXGI); */
|
|
}
|
|
else
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Wrap some funcs and setup remaining SD flags */
|
|
|
|
pXGI->XGI_SD_Flags &= ~(XGI_SD_PSEUDOXINERAMA);
|
|
|
|
pXGI->CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = XGICloseScreen;
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
pScreen->SaveScreen = XGISaveScreenDH;
|
|
else
|
|
#endif
|
|
pScreen->SaveScreen = XGISaveScreen;
|
|
|
|
/* Install BlockHandler */
|
|
pXGI->BlockHandler = pScreen->BlockHandler;
|
|
pScreen->BlockHandler = XGIBlockHandler;
|
|
|
|
/* Report any unused options (only for the first generation) */
|
|
if(serverGeneration == 1)
|
|
{
|
|
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
|
|
}
|
|
|
|
/* Clear frame buffer */
|
|
/* For CRT2, we don't do that at this point in dual head
|
|
* mode since the mode isn't switched at this time (it will
|
|
* be reset when setting the CRT1 mode). Hence, we just
|
|
* save the necessary data and clear the screen when
|
|
* going through this for CRT1.
|
|
*/
|
|
|
|
OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay
|
|
* (pScrn->bitsPerPixel >> 3);
|
|
|
|
/* Turn on the screen now */
|
|
/* We do this in dual head mode after second head is finished */
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->SecondHead)
|
|
{
|
|
bzero(pXGI->FbBase, OnScreenSize);
|
|
bzero(pXGIEnt->FbBase1, pXGIEnt->OnScreenSize1);
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
}
|
|
else
|
|
{
|
|
pXGIEnt->FbBase1 = pXGI->FbBase;
|
|
pXGIEnt->OnScreenSize1 = OnScreenSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
XGISaveScreen(pScreen, SCREEN_SAVER_OFF);
|
|
bzero(pXGI->FbBase, OnScreenSize);
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
pXGI->XGI_SD_Flags &= ~XGI_SD_ISDEPTH8;
|
|
if(pXGI->CurrentLayout.bitsPerPixel == 8)
|
|
{
|
|
pXGI->XGI_SD_Flags |= XGI_SD_ISDEPTH8;
|
|
pXGI->XGI_SD_Flags &= ~XGI_SD_SUPPORTXVGAMMA1;
|
|
}
|
|
PDEBUG(ErrorF("XGIScreenInit() End. \n"));
|
|
XGIDumpPalette(pScrn);
|
|
return TRUE;
|
|
}
|
|
|
|
/* Usually mandatory */
|
|
Bool
|
|
XGISwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
DumpDDIName("XGISwitchMode\n") ;
|
|
|
|
if(!pXGI->NoAccel)
|
|
{
|
|
if(pXGI->AccelInfoPtr)
|
|
{
|
|
(*pXGI->AccelInfoPtr->Sync)(pScrn);
|
|
PDEBUG(ErrorF("XGISwitchMode Accel Enabled. \n"));
|
|
}
|
|
}
|
|
PDEBUG(ErrorF("XGISwitchMode (%d, %d) \n", mode->HDisplay, mode->VDisplay));
|
|
|
|
if(!(XGIModeInit(xf86Screens[scrnIndex], mode))) return FALSE;
|
|
|
|
/* Since RandR (indirectly) uses SwitchMode(), we need to
|
|
* update our Xinerama info here, too, in case of resizing
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
XGISwitchCRT1Status(ScrnInfoPtr pScrn, int onoff)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
DisplayModePtr mode = pScrn->currentMode;
|
|
unsigned long vbflags = pXGI->VBFlags;
|
|
int crt1off;
|
|
|
|
|
|
DumpDDIName("XGISwitchCRT1Status\n") ;
|
|
|
|
/* onoff: 0=OFF, 1=ON(VGA), 2=ON(LCDA) */
|
|
/* Switching to LCDA will disable CRT2 if previously LCD */
|
|
|
|
/* Do NOT use this to switch from CRT1_LCDA to CRT2_LCD */
|
|
|
|
return FALSE;
|
|
|
|
/* Off only if at least one CRT2 device is active */
|
|
if((!onoff) && (!(vbflags & CRT2_ENABLE))) return FALSE;
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode) return FALSE;
|
|
#endif
|
|
|
|
/* Can't switch to LCDA of not supported (duh!) */
|
|
if(!(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTLCDA))
|
|
{
|
|
if(onoff == 2)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"LCD-via-CRT1 not supported on this hardware\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
if(!onoff)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"CRT1 can't be switched off in MergedFB mode\n");
|
|
return FALSE;
|
|
}
|
|
else if(onoff == 2)
|
|
{
|
|
if(vbflags & CRT2_LCD)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"CRT2 type can't be LCD while CRT1 is LCD-via-CRT1\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(mode->Private)
|
|
{
|
|
mode = ((XGIMergedDisplayModePtr)mode->Private)->CRT1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
vbflags &= ~(DISPTYPE_CRT1 | SINGLE_MODE | MIRROR_MODE | CRT1_LCDA);
|
|
crt1off = 1;
|
|
if(onoff > 0)
|
|
{
|
|
vbflags |= DISPTYPE_CRT1;
|
|
crt1off = 0;
|
|
if(onoff == 2)
|
|
{
|
|
vbflags |= CRT1_LCDA;
|
|
vbflags &= ~CRT2_LCD;
|
|
}
|
|
/* Remember: Dualhead not supported */
|
|
if(vbflags & CRT2_ENABLE) vbflags |= MIRROR_MODE;
|
|
else vbflags |= SINGLE_MODE;
|
|
}
|
|
else
|
|
{
|
|
vbflags |= SINGLE_MODE;
|
|
}
|
|
|
|
if(vbflags & CRT1_LCDA)
|
|
{
|
|
if(!XGI_CalcModeIndex(pScrn, mode, vbflags, pXGI->HaveCustomModes))
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Current mode not suitable for LCD-via-CRT1\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pXGI->CRT1off = crt1off;
|
|
pXGI->VBFlags = pXGI->VBFlags_backup = vbflags;
|
|
|
|
/* Sync the accelerators */
|
|
if(!pXGI->NoAccel)
|
|
{
|
|
if(pXGI->AccelInfoPtr)
|
|
{
|
|
(*pXGI->AccelInfoPtr->Sync)(pScrn);
|
|
}
|
|
}
|
|
|
|
if(!(pScrn->SwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0))) return FALSE;
|
|
XGIAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
/* static void
|
|
XGISetStartAddressCRT1(XGIPtr pXGI, unsigned long base)
|
|
{
|
|
unsigned char cr11backup;
|
|
|
|
inXGIIDXREG(XGICR, 0x11, cr11backup);
|
|
andXGIIDXREG(XGICR, 0x11, 0x7F);
|
|
outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
|
|
outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
|
|
outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
|
|
|
|
|
|
setXGIIDXREG(XGICR, 0x11, 0x7F,(cr11backup & 0x80));
|
|
} */
|
|
|
|
#ifdef XGIMERGED
|
|
/* static Bool
|
|
InRegion(int x, int y, region r)
|
|
{
|
|
return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1);
|
|
} */
|
|
|
|
/* static void
|
|
XGIAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned long base;
|
|
|
|
base = y * pXGI->CurrentLayout.displayWidth + x;
|
|
switch(pXGI->CurrentLayout.bitsPerPixel)
|
|
{
|
|
case 16: base >>= 1; break;
|
|
case 32: break;
|
|
default: base >>= 2;
|
|
}
|
|
XGISetStartAddressCRT1(pXGI, base);
|
|
} */
|
|
|
|
/* static void
|
|
XGIMergePointerMoved(int scrnIndex, int x, int y)
|
|
{
|
|
ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn1);
|
|
ScrnInfoPtr pScrn2 = pXGI->CRT2pScrn;
|
|
region out, in1, in2, f2, f1;
|
|
int deltax, deltay;
|
|
|
|
f1.x0 = pXGI->CRT1frameX0;
|
|
f1.x1 = pXGI->CRT1frameX1;
|
|
f1.y0 = pXGI->CRT1frameY0;
|
|
f1.y1 = pXGI->CRT1frameY1;
|
|
f2.x0 = pScrn2->frameX0;
|
|
f2.x1 = pScrn2->frameX1;
|
|
f2.y0 = pScrn2->frameY0;
|
|
f2.y1 = pScrn2->frameY1;
|
|
|
|
out.x0 = pScrn1->frameX0;
|
|
out.x1 = pScrn1->frameX1;
|
|
out.y0 = pScrn1->frameY0;
|
|
out.y1 = pScrn1->frameY1;
|
|
|
|
in1 = out;
|
|
in2 = out;
|
|
switch(((XGIMergedDisplayModePtr)pXGI->CurrentLayout.mode->Private)->CRT2Position)
|
|
{
|
|
case xgiLeftOf:
|
|
in1.x0 = f1.x0;
|
|
in2.x1 = f2.x1;
|
|
break;
|
|
case xgiRightOf:
|
|
in1.x1 = f1.x1;
|
|
in2.x0 = f2.x0;
|
|
break;
|
|
case xgiBelow:
|
|
in1.y1 = f1.y1;
|
|
in2.y0 = f2.y0;
|
|
break;
|
|
case xgiAbove:
|
|
in1.y0 = f1.y0;
|
|
in2.y1 = f2.y1;
|
|
break;
|
|
case xgiClone:
|
|
break;
|
|
}
|
|
|
|
deltay = 0;
|
|
deltax = 0;
|
|
|
|
if(InRegion(x, y, out))
|
|
{
|
|
|
|
if(InRegion(x, y, in1) && !InRegion(x, y, f1))
|
|
{
|
|
REBOUND(f1.x0, f1.x1, x);
|
|
REBOUND(f1.y0, f1.y1, y);
|
|
deltax = 1;
|
|
}
|
|
if(InRegion(x, y, in2) && !InRegion(x, y, f2))
|
|
{
|
|
REBOUND(f2.x0, f2.x1, x);
|
|
REBOUND(f2.y0, f2.y1, y);
|
|
deltax = 1;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if(out.x0 > x)
|
|
{
|
|
deltax = x - out.x0;
|
|
}
|
|
if(out.x1 < x)
|
|
{
|
|
deltax = x - out.x1;
|
|
}
|
|
if(deltax)
|
|
{
|
|
pScrn1->frameX0 += deltax;
|
|
pScrn1->frameX1 += deltax;
|
|
f1.x0 += deltax;
|
|
f1.x1 += deltax;
|
|
f2.x0 += deltax;
|
|
f2.x1 += deltax;
|
|
}
|
|
|
|
if(out.y0 > y)
|
|
{
|
|
deltay = y - out.y0;
|
|
}
|
|
if(out.y1 < y)
|
|
{
|
|
deltay = y - out.y1;
|
|
}
|
|
if(deltay)
|
|
{
|
|
pScrn1->frameY0 += deltay;
|
|
pScrn1->frameY1 += deltay;
|
|
f1.y0 += deltay;
|
|
f1.y1 += deltay;
|
|
f2.y0 += deltay;
|
|
f2.y1 += deltay;
|
|
}
|
|
|
|
switch(((XGIMergedDisplayModePtr)pXGI->CurrentLayout.mode->Private)->CRT2Position)
|
|
{
|
|
case xgiLeftOf:
|
|
if(x >= f1.x0)
|
|
{ REBOUND(f1.y0, f1.y1, y); }
|
|
if(x <= f2.x1)
|
|
{ REBOUND(f2.y0, f2.y1, y); }
|
|
break;
|
|
case xgiRightOf:
|
|
if(x <= f1.x1)
|
|
{ REBOUND(f1.y0, f1.y1, y); }
|
|
if(x >= f2.x0)
|
|
{ REBOUND(f2.y0, f2.y1, y); }
|
|
break;
|
|
case xgiBelow:
|
|
if(y <= f1.y1)
|
|
{ REBOUND(f1.x0, f1.x1, x); }
|
|
if(y >= f2.y0)
|
|
{ REBOUND(f2.x0, f2.x1, x); }
|
|
break;
|
|
case xgiAbove:
|
|
if(y >= f1.y0)
|
|
{ REBOUND(f1.x0, f1.x1, x); }
|
|
if(y <= f2.y1)
|
|
{ REBOUND(f2.x0, f2.x1, x); }
|
|
break;
|
|
case xgiClone:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(deltax || deltay)
|
|
{
|
|
pXGI->CRT1frameX0 = f1.x0;
|
|
pXGI->CRT1frameY0 = f1.y0;
|
|
pScrn2->frameX0 = f2.x0;
|
|
pScrn2->frameY0 = f2.y0;
|
|
|
|
pXGI->CRT1frameX1 = pXGI->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1;
|
|
pXGI->CRT1frameY1 = pXGI->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1;
|
|
pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1;
|
|
pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1;
|
|
pScrn1->frameX1 = pScrn1->frameX0 + pXGI->CurrentLayout.mode->HDisplay - 1;
|
|
pScrn1->frameY1 = pScrn1->frameY0 + pXGI->CurrentLayout.mode->VDisplay - 1;
|
|
|
|
XGIAdjustFrameHW_CRT1(pScrn1, pXGI->CRT1frameX0, pXGI->CRT1frameY0);
|
|
}
|
|
} */
|
|
|
|
|
|
/* static void
|
|
XGIAdjustFrameMerged(int scrnIndex, int x, int y, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn1);
|
|
ScrnInfoPtr pScrn2 = pXGI->CRT2pScrn;
|
|
int VTotal = pXGI->CurrentLayout.mode->VDisplay;
|
|
int HTotal = pXGI->CurrentLayout.mode->HDisplay;
|
|
int VMax = VTotal;
|
|
int HMax = HTotal;
|
|
|
|
BOUND(x, 0, pScrn1->virtualX - HTotal);
|
|
BOUND(y, 0, pScrn1->virtualY - VTotal);
|
|
|
|
switch(SDMPTR(pScrn1)->CRT2Position)
|
|
{
|
|
case xgiLeftOf:
|
|
pScrn2->frameX0 = x;
|
|
BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
|
|
pXGI->CRT1frameX0 = x + CDMPTR->CRT2->HDisplay;
|
|
BOUND(pXGI->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
|
|
break;
|
|
case xgiRightOf:
|
|
pXGI->CRT1frameX0 = x;
|
|
BOUND(pXGI->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
|
|
pScrn2->frameX0 = x + CDMPTR->CRT1->HDisplay;
|
|
BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
|
|
break;
|
|
case xgiAbove:
|
|
BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
|
|
pScrn2->frameY0 = y;
|
|
BOUND(pXGI->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
|
|
pXGI->CRT1frameY0 = y + CDMPTR->CRT2->VDisplay;
|
|
break;
|
|
case xgiBelow:
|
|
BOUND(pXGI->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
|
|
pXGI->CRT1frameY0 = y;
|
|
BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
|
|
pScrn2->frameY0 = y + CDMPTR->CRT1->VDisplay;
|
|
break;
|
|
case xgiClone:
|
|
BOUND(pXGI->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
|
|
BOUND(pXGI->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
|
|
BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
|
|
BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
|
|
break;
|
|
}
|
|
|
|
BOUND(pXGI->CRT1frameX0, 0, pScrn1->virtualX - CDMPTR->CRT1->HDisplay);
|
|
BOUND(pXGI->CRT1frameY0, 0, pScrn1->virtualY - CDMPTR->CRT1->VDisplay);
|
|
BOUND(pScrn2->frameX0, 0, pScrn1->virtualX - CDMPTR->CRT2->HDisplay);
|
|
BOUND(pScrn2->frameY0, 0, pScrn1->virtualY - CDMPTR->CRT2->VDisplay);
|
|
|
|
pScrn1->frameX0 = x;
|
|
pScrn1->frameY0 = y;
|
|
|
|
pXGI->CRT1frameX1 = pXGI->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1;
|
|
pXGI->CRT1frameY1 = pXGI->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1;
|
|
pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1;
|
|
pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1;
|
|
pScrn1->frameX1 = pScrn1->frameX0 + pXGI->CurrentLayout.mode->HDisplay - 1;
|
|
pScrn1->frameY1 = pScrn1->frameY0 + pXGI->CurrentLayout.mode->VDisplay - 1;
|
|
|
|
XGIAdjustFrameHW_CRT1(pScrn1, pXGI->CRT1frameX0, pXGI->CRT1frameY0);
|
|
} */
|
|
#endif
|
|
|
|
/*
|
|
* This function is used to initialize the Start Address - the first
|
|
* displayed location in the video memory.
|
|
*
|
|
* Usually mandatory
|
|
*/
|
|
void
|
|
XGIAdjustFrame(int scrnIndex, int x, int y, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn) ;
|
|
unsigned long base ;
|
|
unsigned char ucSR5Stat, ucTemp ;
|
|
|
|
DumpDDIName("AdjustFrame %d\n",scrnIndex) ;
|
|
inXGIIDXREG(XGISR, 0x05, ucSR5Stat ) ;
|
|
if( ucSR5Stat == 0xA1 ) ucSR5Stat = 0x86 ;
|
|
outXGIIDXREG(XGISR, 0x05, 0x86) ;
|
|
|
|
base = (pScrn->bitsPerPixel + 7 )/8 ;
|
|
base *= x ;
|
|
base += pXGI->scrnOffset * y ;
|
|
base >>= 2 ;
|
|
|
|
switch( pXGI->Chipset )
|
|
{
|
|
case PCI_CHIP_XGIXG40:
|
|
default:
|
|
|
|
ucTemp = base & 0xFF ; outXGIIDXREG( XGICR, 0x0D, ucTemp ) ;
|
|
ucTemp = (base>>8) & 0xFF ; outXGIIDXREG( XGICR, 0x0C, ucTemp ) ;
|
|
ucTemp = (base>>16) & 0xFF ; outXGIIDXREG( XGISR, 0x0D, ucTemp ) ;
|
|
ucTemp = (base>>24) & 0x01 ; setXGIIDXREG( XGISR, 0x37, 0xFE, ucTemp ) ;
|
|
|
|
/* if (pXGI->VBFlags) {
|
|
XGI_UnLockCRT2(&(pXGI->xgi_HwDevExt),pXGI->pVBInfo);
|
|
ucTemp = base & 0xFF ; outXGIIDXREG( XGIPART1, 6 , ucTemp ) ;
|
|
ucTemp = (base>>8) & 0xFF ; outXGIIDXREG( XGIPART1, 5 , ucTemp ) ;
|
|
ucTemp = (base>>16) & 0xFF ; outXGIIDXREG( XGIPART1, 4 , ucTemp ) ;
|
|
ucTemp = (base>>24) & 0x01 ; ucTemp <<= 7 ;
|
|
setXGIIDXREG( XGIPART1, 0x2, 0x7F, ucTemp ) ;
|
|
|
|
XGI_LockCRT2(&(pXGI->xgi_HwDevExt),pXGI->pVBInfo);
|
|
}
|
|
*/
|
|
break ;
|
|
|
|
}
|
|
|
|
outXGIIDXREG(XGISR, 0x05, ucSR5Stat ) ;
|
|
|
|
}
|
|
|
|
/*
|
|
* This is called when VT switching back to the X server. Its job is
|
|
* to reinitialise the video mode.
|
|
* Mandatory!
|
|
*/
|
|
static Bool
|
|
XGIEnterVT(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
|
|
if(!XGIModeInit(pScrn, pScrn->currentMode))
|
|
{
|
|
XGIErrorLog(pScrn, "XGIEnterVT: XGIModeInit() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
XGIAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
|
|
|
|
#ifdef XF86DRI
|
|
/* ScreenPtr pScreen; */
|
|
if(pXGI->directRenderingEnabled)
|
|
{
|
|
DRIUnlock(screenInfo.screens[scrnIndex]);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if((!pXGI->DualHeadMode) || (!pXGI->SecondHead))
|
|
#endif
|
|
if(pXGI->ResetXv)
|
|
{
|
|
(pXGI->ResetXv)(pScrn);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* This is called when VT switching away from the X server. Its job is
|
|
* to restore the previous (text) mode.
|
|
* Mandatory!
|
|
*/
|
|
static void
|
|
XGILeaveVT(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
#ifdef XF86DRI
|
|
ScreenPtr pScreen;
|
|
|
|
PDEBUG(ErrorF("XGILeaveVT()\n")) ;
|
|
if(pXGI->directRenderingEnabled)
|
|
{
|
|
pScreen = screenInfo.screens[scrnIndex];
|
|
DRILock(pScreen, 0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode && pXGI->SecondHead) return;
|
|
#endif
|
|
|
|
if(pXGI->CursorInfoPtr)
|
|
{
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(!pXGI->SecondHead)
|
|
{
|
|
pXGI->ForceCursorOff = TRUE;
|
|
pXGI->CursorInfoPtr->HideCursor(pScrn);
|
|
XGIWaitVBRetrace(pScrn);
|
|
pXGI->ForceCursorOff = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pXGI->CursorInfoPtr->HideCursor(pScrn);
|
|
XGIWaitVBRetrace(pScrn);
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
XGIBridgeRestore(pScrn);
|
|
|
|
if(pXGI->UseVESA)
|
|
{
|
|
|
|
/* This is a q&d work-around for a BIOS bug. In case we disabled CRT2,
|
|
* VBESaveRestore() does not restore CRT1. So we set any mode now,
|
|
* because VBESetVBEMode correctly restores CRT1. Afterwards, we
|
|
* can call VBESaveRestore to restore original mode.
|
|
*/
|
|
if((pXGI->XGI_Pr->XGI_VBType & VB_XGIVB) && (!(pXGI->VBFlags & DISPTYPE_DISP2)))
|
|
VBESetVBEMode(pXGI->pVbe, (pXGI->XGIVESAModeList->n) | 0xc000, NULL);
|
|
|
|
XGIVESARestore(pScrn);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
XGIRestore(pScrn);
|
|
|
|
}
|
|
|
|
/* We use (otherwise unused) bit 7 to indicate that we are running
|
|
* to keep xgifb to change the displaymode (this would result in
|
|
* lethal display corruption upon quitting X or changing to a VT
|
|
* until a reboot)
|
|
*/
|
|
|
|
vgaHWLock(hwp);
|
|
}
|
|
|
|
|
|
/*
|
|
* This is called at the end of each server generation. It restores the
|
|
* original (text) mode. It should really also unmap the video memory too.
|
|
* Mandatory!
|
|
*/
|
|
static Bool
|
|
XGICloseScreen(int scrnIndex, ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
#ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = pXGI->entityPrivate;
|
|
#endif
|
|
|
|
#ifdef XF86DRI
|
|
if(pXGI->directRenderingEnabled)
|
|
{
|
|
XGIDRICloseScreen(pScreen);
|
|
pXGI->directRenderingEnabled = FALSE;
|
|
}
|
|
#endif
|
|
|
|
if(pScrn->vtSema)
|
|
{
|
|
|
|
if(pXGI->CursorInfoPtr)
|
|
{
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(!pXGI->SecondHead)
|
|
{
|
|
pXGI->ForceCursorOff = TRUE;
|
|
pXGI->CursorInfoPtr->HideCursor(pScrn);
|
|
XGIWaitVBRetrace(pScrn);
|
|
pXGI->ForceCursorOff = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pXGI->CursorInfoPtr->HideCursor(pScrn);
|
|
XGIWaitVBRetrace(pScrn);
|
|
#ifdef XGIDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
XGIBridgeRestore(pScrn);
|
|
|
|
if(pXGI->UseVESA)
|
|
{
|
|
|
|
/* This is a q&d work-around for a BIOS bug. In case we disabled CRT2,
|
|
* VBESaveRestore() does not restore CRT1. So we set any mode now,
|
|
* because VBESetVBEMode correctly restores CRT1. Afterwards, we
|
|
* can call VBESaveRestore to restore original mode.
|
|
*/
|
|
if((pXGI->XGI_Pr->XGI_VBType & VB_XGIVB) && (!(pXGI->VBFlags & DISPTYPE_DISP2)))
|
|
VBESetVBEMode(pXGI->pVbe, (pXGI->XGIVESAModeList->n) | 0xc000, NULL);
|
|
|
|
XGIVESARestore(pScrn);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
XGIRestore(pScrn);
|
|
|
|
}
|
|
|
|
vgaHWLock(hwp);
|
|
|
|
}
|
|
|
|
/* We should restore the mode number in case vtsema = false as well,
|
|
* but since we haven't register access then we can't do it. I think
|
|
* I need to rework the save/restore stuff, like saving the video
|
|
* status when returning to the X server and by that save me the
|
|
* trouble if xgifb was started from a textmode VT while X was on.
|
|
*/
|
|
|
|
XGIUnmapMem(pScrn);
|
|
vgaHWUnmapMem(pScrn);
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
pXGIEnt = pXGI->entityPrivate;
|
|
pXGIEnt->refCount--;
|
|
}
|
|
#endif
|
|
|
|
if(pXGI->pInt)
|
|
{
|
|
xf86FreeInt10(pXGI->pInt);
|
|
pXGI->pInt = NULL;
|
|
}
|
|
|
|
if(pXGI->AccelLinearScratch)
|
|
{
|
|
xf86FreeOffscreenLinear(pXGI->AccelLinearScratch);
|
|
pXGI->AccelLinearScratch = NULL;
|
|
}
|
|
|
|
if(pXGI->AccelInfoPtr)
|
|
{
|
|
XAADestroyInfoRec(pXGI->AccelInfoPtr);
|
|
pXGI->AccelInfoPtr = NULL;
|
|
}
|
|
|
|
if(pXGI->CursorInfoPtr)
|
|
{
|
|
xf86DestroyCursorInfoRec(pXGI->CursorInfoPtr);
|
|
pXGI->CursorInfoPtr = NULL;
|
|
}
|
|
|
|
if(pXGI->ShadowPtr)
|
|
{
|
|
xfree(pXGI->ShadowPtr);
|
|
pXGI->ShadowPtr = NULL;
|
|
}
|
|
|
|
if(pXGI->DGAModes)
|
|
{
|
|
xfree(pXGI->DGAModes);
|
|
pXGI->DGAModes = NULL;
|
|
}
|
|
|
|
if(pXGI->adaptor)
|
|
{
|
|
xfree(pXGI->adaptor);
|
|
pXGI->adaptor = NULL;
|
|
pXGI->ResetXv = pXGI->ResetXvGamma = NULL;
|
|
}
|
|
|
|
pScrn->vtSema = FALSE;
|
|
|
|
/* Restore Blockhandler */
|
|
pScreen->BlockHandler = pXGI->BlockHandler;
|
|
|
|
pScreen->CloseScreen = pXGI->CloseScreen;
|
|
|
|
return(*pScreen->CloseScreen)(scrnIndex, pScreen);
|
|
}
|
|
|
|
|
|
/* Free up any per-generation data structures */
|
|
|
|
/* Optional */
|
|
static void
|
|
XGIFreeScreen(int scrnIndex, int flags)
|
|
{
|
|
if(xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
|
|
{
|
|
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
XGIFreeRec(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
|
|
/* Checks if a mode is suitable for the selected chipset. */
|
|
|
|
static int
|
|
XGIValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
int HDisplay = mode->HDisplay ;
|
|
int VDisplay = mode->VDisplay ;
|
|
int Clock = mode->Clock;
|
|
int i = 0;
|
|
int VRefresh ;
|
|
|
|
VRefresh = (int)((float)(Clock*1000)/(float)(mode->VTotal*mode->HTotal)+0.5) ;
|
|
|
|
PDEBUG5(ErrorF("XGIValidMode()."));
|
|
PDEBUG5(ErrorF("CLK=%5.3fMhz %dx%d@%d ",(float)Clock/1000, HDisplay, VDisplay, VRefresh));
|
|
PDEBUG5(ErrorF("(VT,HT)=(%d,%d)\n",mode->VTotal ,mode->HTotal)) ;
|
|
|
|
if(pXGI->VBFlags & CRT2_LCD)
|
|
{
|
|
if( (HDisplay > 1600 && VDisplay > 1200 )
|
|
||(HDisplay < 640 && VDisplay < 480 ))
|
|
{
|
|
PDEBUG5(ErrorF("skip by LCD limit\n")) ;
|
|
return(MODE_NOMODE) ;
|
|
}
|
|
/* if( VRefresh != 60) return(MODE_NOMODE) ; */
|
|
}
|
|
else if( pXGI->VBFlags & CRT2_TV )
|
|
{
|
|
if((HDisplay > 1024 && VDisplay > 768 )||
|
|
(HDisplay < 640 && VDisplay < 480 )||
|
|
(VRefresh != 60))
|
|
{
|
|
PDEBUG5(ErrorF("skip by TV limit\n")) ;
|
|
return(MODE_NOMODE) ;
|
|
}
|
|
}
|
|
else if( pXGI->VBFlags & CRT2_VGA )
|
|
{
|
|
if( (HDisplay > 1600 && VDisplay > 1200)||
|
|
(HDisplay < 640 && VDisplay < 480))
|
|
{
|
|
PDEBUG5(ErrorF("skip by CRT2 limit\n")) ;
|
|
return(MODE_NOMODE) ;
|
|
}
|
|
}
|
|
|
|
if( pXGI->Chipset == PCI_CHIP_XGIXG20 )
|
|
{
|
|
XgiMode = XG20_Mode ;
|
|
}
|
|
else
|
|
{
|
|
XgiMode = XGI_Mode ;
|
|
}
|
|
|
|
while ( (XgiMode[i].Clock != Clock) ||
|
|
(XgiMode[i].HDisplay != HDisplay) ||
|
|
(XgiMode[i].VDisplay != VDisplay) )
|
|
{
|
|
if (XgiMode[i].Clock == 0)
|
|
{
|
|
PDEBUG5(ErrorF("--- NO_Mode support for %dx%d@%dHz\n",HDisplay,VDisplay,VRefresh));
|
|
return(MODE_NOMODE) ;
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
PDEBUG5(ErrorF("Mode OK\n")) ;
|
|
|
|
return(MODE_OK);
|
|
}
|
|
|
|
/* Do screen blanking
|
|
*
|
|
* Mandatory
|
|
*/
|
|
static Bool
|
|
XGISaveScreen(ScreenPtr pScreen, int mode)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
|
|
if((pScrn != NULL) && pScrn->vtSema)
|
|
{
|
|
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
#endif
|
|
}
|
|
|
|
return vgaHWSaveScreen(pScreen, mode);
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
/* SaveScreen for dual head mode */
|
|
static Bool
|
|
XGISaveScreenDH(ScreenPtr pScreen, int mode)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
Bool checkit = FALSE;
|
|
|
|
if((pScrn != NULL) && pScrn->vtSema)
|
|
{
|
|
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
if((pXGI->SecondHead) && ((!(pXGI->VBFlags & CRT1_LCDA)) || (pXGI->XGI_Pr->XGI_VBType& VB_XGI301C)))
|
|
{
|
|
|
|
/* Slave head is always CRT1 */
|
|
if(pXGI->VBFlags & CRT1_LCDA) pXGI->Blank = xf86IsUnblank(mode) ? FALSE : TRUE;
|
|
|
|
return vgaHWSaveScreen(pScreen, mode);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Master head is always CRT2 */
|
|
/* But we land here if CRT1 is LCDA, too */
|
|
|
|
/* We can only blank LCD, not other CRT2 devices */
|
|
if(!(pXGI->VBFlags & (CRT2_LCD|CRT1_LCDA))) return TRUE;
|
|
|
|
/* enable access to extended sequencer registers */
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
#endif
|
|
if(checkit)
|
|
{
|
|
if(!pXGI->SecondHead) pXGI->BlankCRT2 = xf86IsUnblank(mode) ? FALSE : TRUE;
|
|
else if(pXGI->VBFlags & CRT1_LCDA) pXGI->Blank = xf86IsUnblank(mode) ? FALSE : TRUE;
|
|
}
|
|
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
static void
|
|
XGIDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal);
|
|
xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted);
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
XGIModifyModeInfo(DisplayModePtr mode)
|
|
{
|
|
if(mode->CrtcHBlankStart == mode->CrtcHDisplay)
|
|
mode->CrtcHBlankStart++;
|
|
if(mode->CrtcHBlankEnd == mode->CrtcHTotal)
|
|
mode->CrtcHBlankEnd--;
|
|
if(mode->CrtcVBlankStart == mode->CrtcVDisplay)
|
|
mode->CrtcVBlankStart++;
|
|
if(mode->CrtcVBlankEnd == mode->CrtcVTotal)
|
|
mode->CrtcVBlankEnd--;
|
|
}
|
|
|
|
/* Enable the Turboqueue/Commandqueue (For 300 and 315/330 series only) */
|
|
void
|
|
XGIEnableTurboQueue(ScrnInfoPtr pScrn)
|
|
{
|
|
/* XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned short SR26, SR27;
|
|
unsigned long temp; */
|
|
}
|
|
|
|
/* Things to do before a ModeSwitch. We set up the
|
|
* video bridge configuration and the TurboQueue.
|
|
*/
|
|
void XGIPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned char CR30, CR31, CR32, CR33;
|
|
unsigned char CR3B = 0;
|
|
unsigned char CR17, CR38 = 0;
|
|
unsigned char CR35 = 0, CR79 = 0;
|
|
unsigned long vbflag;
|
|
int temp = 0, i;
|
|
int crt1rateindex = 0;
|
|
DisplayModePtr mymode;
|
|
#ifdef XGIMERGED
|
|
DisplayModePtr mymode2 = NULL;
|
|
#endif
|
|
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
mymode = ((XGIMergedDisplayModePtr)mode->Private)->CRT1;
|
|
mymode2 = ((XGIMergedDisplayModePtr)mode->Private)->CRT2;
|
|
}
|
|
else
|
|
#endif
|
|
mymode = mode;
|
|
|
|
vbflag = pXGI->VBFlags;
|
|
PDEBUG(ErrorF("VBFlags=0x%lx\n", pXGI->VBFlags));
|
|
pXGI->IsCustom = FALSE;
|
|
#ifdef XGIMERGED
|
|
pXGI->IsCustomCRT2 = FALSE;
|
|
|
|
if(pXGI->MergedFB)
|
|
{
|
|
/* CRT2 */
|
|
if(vbflag & CRT2_LCD)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_HaveCustomData)
|
|
{
|
|
for(i=0; i<7; i++)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_DataValid[i])
|
|
{
|
|
if((mymode2->HDisplay == pXGI->XGI_Pr->CP_HDisplay[i]) &&
|
|
(mymode2->VDisplay == pXGI->XGI_Pr->CP_VDisplay[i]))
|
|
{
|
|
if(mymode2->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustomCRT2 = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(vbflag & (CRT2_VGA|CRT2_LCD))
|
|
{
|
|
if(pXGI->AddedPlasmaModes)
|
|
{
|
|
if(mymode2->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustomCRT2 = TRUE;
|
|
}
|
|
}
|
|
if(pXGI->HaveCustomModes2)
|
|
{
|
|
if(!(mymode2->type & M_T_DEFAULT))
|
|
{
|
|
pXGI->IsCustomCRT2 = TRUE;
|
|
}
|
|
}
|
|
}
|
|
/* CRT1 */
|
|
if(pXGI->HaveCustomModes)
|
|
{
|
|
if(!(mymode->type & M_T_DEFAULT))
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(!pXGI->SecondHead)
|
|
{
|
|
/* CRT2 */
|
|
if(vbflag & CRT2_LCD)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_HaveCustomData)
|
|
{
|
|
for(i=0; i<7; i++)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_DataValid[i])
|
|
{
|
|
if((mymode->HDisplay == pXGI->XGI_Pr->CP_HDisplay[i]) &&
|
|
(mymode->VDisplay == pXGI->XGI_Pr->CP_VDisplay[i]))
|
|
{
|
|
if(mymode->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(vbflag & (CRT2_VGA|CRT2_LCD))
|
|
{
|
|
if(pXGI->AddedPlasmaModes)
|
|
{
|
|
if(mymode->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
if(pXGI->HaveCustomModes)
|
|
{
|
|
if(!(mymode->type & M_T_DEFAULT))
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* CRT1 */
|
|
if(pXGI->HaveCustomModes)
|
|
{
|
|
if(!(mymode->type & M_T_DEFAULT))
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if(vbflag & CRT2_LCD)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_HaveCustomData)
|
|
{
|
|
for(i=0; i<7; i++)
|
|
{
|
|
if(pXGI->XGI_Pr->CP_DataValid[i])
|
|
{
|
|
if((mymode->HDisplay == pXGI->XGI_Pr->CP_HDisplay[i]) &&
|
|
(mymode->VDisplay == pXGI->XGI_Pr->CP_VDisplay[i]))
|
|
{
|
|
if(mymode->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(vbflag & (CRT2_LCD|CRT2_VGA))
|
|
{
|
|
if(pXGI->AddedPlasmaModes)
|
|
{
|
|
if(mymode->type & M_T_BUILTIN)
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if((pXGI->HaveCustomModes) && (!(vbflag & CRT2_TV)))
|
|
{
|
|
if(!(mymode->type & M_T_DEFAULT))
|
|
{
|
|
pXGI->IsCustom = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL); /* Unlock Registers */
|
|
#endif
|
|
|
|
inXGIIDXREG(XGICR, 0x30, CR30);
|
|
inXGIIDXREG(XGICR, 0x31, CR31);
|
|
CR32 = pXGI->newCR32;
|
|
inXGIIDXREG(XGICR, 0x33, CR33);
|
|
|
|
inXGIIDXREG(XGICR, 0x3b, CR3B);
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 4,
|
|
"Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n",
|
|
CR30, CR31, CR32, CR33, temp, CR38);
|
|
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "VBFlags=0x%lx\n", pXGI->VBFlags);
|
|
|
|
CR30 = 0x00;
|
|
CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */
|
|
CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */
|
|
CR35 = 0x00;
|
|
|
|
|
|
if(!pXGI->AllowHotkey)
|
|
{
|
|
CR31 |= 0x80; /* Disable hotkey-switch */
|
|
}
|
|
CR79 &= ~0x10; /* Enable Backlight control on 315 series */
|
|
|
|
XGI_SetEnableDstn(pXGI->XGI_Pr, FALSE);
|
|
XGI_SetEnableFstn(pXGI->XGI_Pr, FALSE);
|
|
|
|
if((vbflag & CRT1_LCDA) && (viewmode == XGI_MODE_CRT1))
|
|
{
|
|
|
|
CR38 |= 0x02;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA))
|
|
{
|
|
|
|
case CRT2_TV:
|
|
|
|
CR38 &= ~0xC0; /* Clear Pal M/N bits */
|
|
|
|
if(vbflag & TV_YPBPR)
|
|
{ /* Video bridge */
|
|
if(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPR)
|
|
{
|
|
CR30 |= 0x80;
|
|
CR38 |= 0x08;
|
|
if(vbflag & TV_YPBPR525P) CR38 |= 0x10;
|
|
else if(vbflag & TV_YPBPR750P) CR38 |= 0x20;
|
|
else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30;
|
|
CR31 &= ~0x01;
|
|
if(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPRAR)
|
|
{
|
|
CR3B &= ~0x03;
|
|
if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00;
|
|
else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03;
|
|
else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01;
|
|
else CR3B |= 0x03;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ /* All */
|
|
if(vbflag & TV_SCART) CR30 |= 0x10;
|
|
if(vbflag & TV_SVIDEO) CR30 |= 0x08;
|
|
if(vbflag & TV_AVIDEO) CR30 |= 0x04;
|
|
if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */
|
|
|
|
if(vbflag & TV_PAL)
|
|
{
|
|
CR31 |= 0x01;
|
|
CR35 |= 0x01;
|
|
if( pXGI->XGI_Pr->XGI_VBType & VB_XGIVB )
|
|
{
|
|
if(vbflag & TV_PALM)
|
|
{
|
|
CR38 |= 0x40;
|
|
CR35 |= 0x04;
|
|
}
|
|
else if(vbflag & TV_PALN)
|
|
{
|
|
CR38 |= 0x80;
|
|
CR35 |= 0x08;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CR31 &= ~0x01;
|
|
CR35 &= ~0x01;
|
|
if(vbflag & TV_NTSCJ)
|
|
{
|
|
CR38 |= 0x40; /* TW, not BIOS */
|
|
CR35 |= 0x02;
|
|
}
|
|
}
|
|
if(vbflag & TV_SCART)
|
|
{
|
|
CR31 |= 0x01;
|
|
CR35 |= 0x01;
|
|
}
|
|
}
|
|
|
|
CR31 &= ~0x04; /* Clear NotSimuMode */
|
|
pXGI->XGI_Pr->XGI_CHOverScan = pXGI->UseCHOverScan;
|
|
if((pXGI->OptTVSOver == 1) && (pXGI->ChrontelType == CHRONTEL_700x))
|
|
{
|
|
pXGI->XGI_Pr->XGI_CHSOverScan = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pXGI->XGI_Pr->XGI_CHSOverScan = FALSE;
|
|
}
|
|
#ifdef XGI_CP
|
|
XGI_CP_DRIVER_CONFIG
|
|
#endif
|
|
break;
|
|
|
|
case CRT2_LCD:
|
|
CR30 |= 0x20;
|
|
XGI_SetEnableDstn(pXGI->XGI_Pr, pXGI->DSTN);
|
|
XGI_SetEnableFstn(pXGI->XGI_Pr, pXGI->FSTN);
|
|
break;
|
|
|
|
case CRT2_VGA:
|
|
CR30 |= 0x40;
|
|
break;
|
|
|
|
default:
|
|
CR30 |= 0x00;
|
|
CR31 |= 0x20; /* VB_OUTPUT_DISABLE */
|
|
if(pXGI->UseVESA)
|
|
{
|
|
crt1rateindex = XGISearchCRT1Rate(pScrn, mymode);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(vbflag & CRT1_LCDA)
|
|
{
|
|
switch(viewmode)
|
|
{
|
|
case XGI_MODE_CRT1:
|
|
CR38 |= 0x01;
|
|
break;
|
|
case XGI_MODE_CRT2:
|
|
if(vbflag & (CRT2_TV|CRT2_VGA))
|
|
{
|
|
CR30 |= 0x02;
|
|
CR38 |= 0x01;
|
|
}
|
|
else
|
|
{
|
|
CR38 |= 0x03;
|
|
}
|
|
break;
|
|
case XGI_MODE_SIMU:
|
|
default:
|
|
if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA))
|
|
{
|
|
CR30 |= 0x01;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA))
|
|
{
|
|
CR30 |= 0x01;
|
|
}
|
|
}
|
|
|
|
/* for VESA: no DRIVERMODE, otherwise
|
|
* -) CRT2 will not be initialized correctly when using mode
|
|
* where LCD has to scale, and
|
|
* -) CRT1 will have too low rate
|
|
*/
|
|
if(pXGI->UseVESA)
|
|
{
|
|
CR31 &= ~0x40; /* Clear Drivermode */
|
|
CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */
|
|
#ifdef TWDEBUG
|
|
CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */
|
|
crt1rateindex = XGISearchCRT1Rate(pScrn, mymode);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
CR31 |= 0x40; /* Set Drivermode */
|
|
CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */
|
|
if(!pXGI->IsCustom)
|
|
{
|
|
crt1rateindex = XGISearchCRT1Rate(pScrn, mymode);
|
|
}
|
|
else
|
|
{
|
|
crt1rateindex = CR33;
|
|
}
|
|
}
|
|
|
|
#ifdef XGIDUALHEAD
|
|
if(pXGI->DualHeadMode)
|
|
{
|
|
if(pXGI->SecondHead)
|
|
{
|
|
/* CRT1 */
|
|
CR33 &= 0xf0;
|
|
if(!(vbflag & CRT1_LCDA))
|
|
{
|
|
CR33 |= (crt1rateindex & 0x0f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* CRT2 */
|
|
CR33 &= 0x0f;
|
|
if(vbflag & CRT2_VGA)
|
|
{
|
|
CR33 |= ((crt1rateindex << 4) & 0xf0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef XGIMERGED
|
|
if(pXGI->MergedFB)
|
|
{
|
|
CR33 = 0;
|
|
if(!(vbflag & CRT1_LCDA))
|
|
{
|
|
CR33 |= (crt1rateindex & 0x0f);
|
|
}
|
|
if(vbflag & CRT2_VGA)
|
|
{
|
|
if(!pXGI->IsCustomCRT2)
|
|
{
|
|
CR33 |= (XGISearchCRT1Rate(pScrn, mymode2) << 4);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
CR33 = 0;
|
|
if(!(vbflag & CRT1_LCDA))
|
|
{
|
|
CR33 |= (crt1rateindex & 0x0f);
|
|
}
|
|
if(vbflag & CRT2_VGA)
|
|
{
|
|
CR33 |= ((crt1rateindex & 0x0f) << 4);
|
|
}
|
|
if((!(pXGI->UseVESA)) && (vbflag & CRT2_ENABLE))
|
|
{
|
|
if(pXGI->CRT1off) CR33 &= 0xf0;
|
|
}
|
|
}
|
|
outXGIIDXREG(XGICR, 0x30, CR30);
|
|
outXGIIDXREG(XGICR, 0x31, CR31);
|
|
outXGIIDXREG(XGICR, 0x33, CR33);
|
|
if(temp)
|
|
{
|
|
outXGIIDXREG(XGICR, temp, CR38);
|
|
}
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
|
|
"After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n",
|
|
CR30, CR31, CR33, temp, CR38);
|
|
|
|
pXGI->XGI_Pr->XGI_UseOEM = pXGI->OptUseOEM;
|
|
|
|
/* Enable TurboQueue */
|
|
#ifdef XGIVRAMQ
|
|
if(pXGI->VGAEngine != XGI_315_VGA)
|
|
#endif
|
|
XGIEnableTurboQueue(pScrn);
|
|
|
|
if((!pXGI->UseVESA) && (pXGI->VBFlags & CRT2_ENABLE))
|
|
{
|
|
/* Switch on CRT1 for modes that require the bridge in SlaveMode */
|
|
andXGIIDXREG(XGISR,0x1f,0x3f);
|
|
inXGIIDXREG(XGICR, 0x17, CR17);
|
|
if(!(CR17 & 0x80))
|
|
{
|
|
orXGIIDXREG(XGICR, 0x17, 0x80);
|
|
outXGIIDXREG(XGISR, 0x00, 0x01);
|
|
usleep(10000);
|
|
outXGIIDXREG(XGISR, 0x00, 0x03);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* PostSetMode:
|
|
* -) Disable CRT1 for saving bandwidth. This doesn't work with VESA;
|
|
* VESA uses the bridge in SlaveMode and switching CRT1 off while
|
|
* the bridge is in SlaveMode not that clever...
|
|
* -) Check if overlay can be used (depending on dotclock)
|
|
* -) Check if Panel Scaler is active on LVDS for overlay re-scaling
|
|
* -) Save TV registers for further processing
|
|
* -) Apply TV settings
|
|
*/
|
|
static void
|
|
XGIPostSetMode(ScrnInfoPtr pScrn, XGIRegPtr xgiReg)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
/* #ifdef XGIDUALHEAD
|
|
XGIEntPtr pXGIEnt = pXGI->entityPrivate;
|
|
#endif */
|
|
/* unsigned char usScratchCR17;
|
|
Bool flag = FALSE;
|
|
Bool doit = TRUE; */
|
|
int myclock;
|
|
unsigned char sr2b, sr2c, tmpreg;
|
|
float num, denum, postscalar, divider;
|
|
PDEBUG(ErrorF(" XGIPostSetMode(). \n"));
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"CRT1off is %d\n", pXGI->CRT1off);
|
|
#endif
|
|
pXGI->CRT1isoff = pXGI->CRT1off;
|
|
|
|
#ifdef UNLOCK_ALWAYS
|
|
xgiSaveUnlockExtRegisterLock(pXGI, NULL, NULL);
|
|
#endif
|
|
|
|
/* Determine if the video overlay can be used */
|
|
if(!pXGI->NoXvideo)
|
|
{
|
|
inXGIIDXREG(XGISR,0x2b,sr2b);
|
|
inXGIIDXREG(XGISR,0x2c,sr2c);
|
|
divider = (sr2b & 0x80) ? 2.0 : 1.0;
|
|
postscalar = (sr2c & 0x80) ?
|
|
( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) :
|
|
( ((sr2c >> 5) & 0x03) + 1.0 );
|
|
num = (sr2b & 0x7f) + 1.0;
|
|
denum = (sr2c & 0x1f) + 1.0;
|
|
myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000);
|
|
|
|
pXGI->MiscFlags &= ~(MISC_CRT1OVERLAY | MISC_CRT1OVERLAYGAMMA);
|
|
/* switch(pXGI->xgi_HwDevExt.jChipType) {
|
|
break;
|
|
}
|
|
*/
|
|
if(!(pXGI->MiscFlags & MISC_CRT1OVERLAY))
|
|
{
|
|
#ifdef XGIDUALHEAD
|
|
if((!pXGI->DualHeadMode) || (pXGI->SecondHead))
|
|
#endif
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3,
|
|
"Current dotclock (%dMhz) too high for video overlay on CRT1\n",
|
|
myclock);
|
|
}
|
|
}
|
|
|
|
/* Determine if the Panel Link scaler is active */
|
|
pXGI->MiscFlags &= ~MISC_PANELLINKSCALER;
|
|
if(pXGI->VBFlags & (CRT2_LCD | CRT1_LCDA))
|
|
{
|
|
if(pXGI->VBFlags & CRT1_LCDA)
|
|
{
|
|
inXGIIDXREG(XGIPART1,0x35,tmpreg);
|
|
tmpreg &= 0x04;
|
|
if(!tmpreg) pXGI->MiscFlags |= MISC_PANELLINKSCALER;
|
|
}
|
|
}
|
|
|
|
/* Determine if our very special TV mode is active */
|
|
pXGI->MiscFlags &= ~MISC_TVNTSC1024;
|
|
if((pXGI->XGI_Pr->XGI_VBType & VB_XGIVB) && (pXGI->VBFlags & CRT2_TV) && (!(pXGI->VBFlags & TV_HIVISION)))
|
|
{
|
|
if( ((pXGI->VBFlags & TV_YPBPR) && (pXGI->VBFlags & TV_YPBPR525I)) ||
|
|
((!(pXGI->VBFlags & TV_YPBPR)) && (pXGI->VBFlags & (TV_NTSC | TV_PALM))) )
|
|
{
|
|
inXGIIDXREG(XGICR,0x34,tmpreg);
|
|
tmpreg &= 0x7f;
|
|
if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38))
|
|
{
|
|
pXGI->MiscFlags |= MISC_TVNTSC1024;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Reset XV gamma correction */
|
|
if(pXGI->ResetXvGamma)
|
|
{
|
|
(pXGI->ResetXvGamma)(pScrn);
|
|
}
|
|
|
|
/* Apply TV settings given by options
|
|
Do this even in DualHeadMode:
|
|
- if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1
|
|
- if this is called by SetModeCRT2, CRT2 mode has changed (duh!)
|
|
-> Hence, in both cases, the settings must be re-applied.
|
|
*/
|
|
}
|
|
|
|
/* Check if video bridge is in slave mode */
|
|
BOOLEAN
|
|
XGIBridgeIsInSlaveMode(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
unsigned char usScratchP1_00;
|
|
|
|
if(!(pXGI->XGI_Pr->XGI_VBType & VB_XGIVB)) return FALSE;
|
|
|
|
inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Build a list of the VESA modes the BIOS reports as valid */
|
|
static void
|
|
XGIBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
int i = 0;
|
|
|
|
while(vbe->VideoModePtr[i] != 0xffff)
|
|
{
|
|
xgiModeInfoPtr m;
|
|
VbeModeInfoBlock *mode;
|
|
int id = vbe->VideoModePtr[i++];
|
|
int bpp;
|
|
|
|
if((mode = VBEGetModeInfo(pVbe, id)) == NULL)
|
|
continue;
|
|
|
|
bpp = mode->BitsPerPixel;
|
|
|
|
m = xnfcalloc(sizeof(xgiModeInfoRec),1);
|
|
m->width = mode->XResolution;
|
|
m->height = mode->YResolution;
|
|
m->bpp = bpp;
|
|
m->n = id;
|
|
m->next = pXGI->XGIVESAModeList;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"BIOS supports VESA mode 0x%x: x:%i y:%i bpp:%i\n",
|
|
m->n, m->width, m->height, m->bpp);
|
|
|
|
pXGI->XGIVESAModeList = m;
|
|
|
|
VBEFreeModeInfo(mode);
|
|
}
|
|
}
|
|
|
|
/* Calc VESA mode from given resolution/depth */
|
|
static UShort
|
|
XGICalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
xgiModeInfoPtr m = pXGI->XGIVESAModeList;
|
|
UShort i = (pScrn->bitsPerPixel+7)/8 - 1;
|
|
UShort ModeIndex = 0;
|
|
|
|
while(m)
|
|
{
|
|
if(pScrn->bitsPerPixel == m->bpp &&
|
|
mode->HDisplay == m->width &&
|
|
mode->VDisplay == m->height)
|
|
return m->n;
|
|
m = m->next;
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"No valid BIOS VESA mode found for %dx%dx%d; searching built-in table.\n",
|
|
mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel);
|
|
|
|
switch(mode->HDisplay)
|
|
{
|
|
case 320:
|
|
if(mode->VDisplay == 200)
|
|
ModeIndex = VESAModeIndex_320x200[i];
|
|
else if(mode->VDisplay == 240)
|
|
ModeIndex = VESAModeIndex_320x240[i];
|
|
break;
|
|
case 400:
|
|
if(mode->VDisplay == 300)
|
|
ModeIndex = VESAModeIndex_400x300[i];
|
|
break;
|
|
case 512:
|
|
if(mode->VDisplay == 384)
|
|
ModeIndex = VESAModeIndex_512x384[i];
|
|
break;
|
|
case 640:
|
|
if(mode->VDisplay == 480)
|
|
ModeIndex = VESAModeIndex_640x480[i];
|
|
else if(mode->VDisplay == 400)
|
|
ModeIndex = VESAModeIndex_640x400[i];
|
|
break;
|
|
case 800:
|
|
if(mode->VDisplay == 600)
|
|
ModeIndex = VESAModeIndex_800x600[i];
|
|
break;
|
|
case 1024:
|
|
if(mode->VDisplay == 768)
|
|
ModeIndex = VESAModeIndex_1024x768[i];
|
|
break;
|
|
case 1280:
|
|
if(mode->VDisplay == 1024)
|
|
ModeIndex = VESAModeIndex_1280x1024[i];
|
|
break;
|
|
case 1600:
|
|
if(mode->VDisplay == 1200)
|
|
ModeIndex = VESAModeIndex_1600x1200[i];
|
|
break;
|
|
case 1920:
|
|
if(mode->VDisplay == 1440)
|
|
ModeIndex = VESAModeIndex_1920x1440[i];
|
|
break;
|
|
}
|
|
|
|
if(!ModeIndex) xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"No valid mode found for %dx%dx%d in built-in table either.\n",
|
|
mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel);
|
|
|
|
return(ModeIndex);
|
|
}
|
|
|
|
USHORT
|
|
XGI_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned long VBFlags, BOOLEAN havecustommodes)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
UShort i = (pXGI->CurrentLayout.bitsPerPixel+7)/8 - 1;
|
|
|
|
if(!(VBFlags & CRT1_LCDA))
|
|
{
|
|
if((havecustommodes) && (!(mode->type & M_T_DEFAULT)))
|
|
{
|
|
return 0xfe;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((mode->HDisplay > pXGI->LCDwidth) ||
|
|
(mode->VDisplay > pXGI->LCDheight))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return(XGI_GetModeID(pXGI->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay,
|
|
i, pXGI->FSTN, pXGI->LCDwidth, pXGI->LCDheight));
|
|
}
|
|
|
|
USHORT
|
|
XGI_CheckCalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned long VBFlags, BOOLEAN havecustommodes)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
/* UShort i = (pXGI->CurrentLayout.bitsPerPixel+7)/8 - 1; */
|
|
UShort ModeIndex = 0;
|
|
int j;
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %x, mode %dx%d)\n",
|
|
VBFlags,mode->HDisplay, mode->VDisplay);
|
|
#endif
|
|
|
|
if(VBFlags & CRT2_LCD)
|
|
{ /* CRT2 is LCD */
|
|
|
|
if(pXGI->XGI_Pr->CP_HaveCustomData)
|
|
{
|
|
for(j=0; j<7; j++)
|
|
{
|
|
if((pXGI->XGI_Pr->CP_DataValid[j]) &&
|
|
(mode->HDisplay == pXGI->XGI_Pr->CP_HDisplay[j]) &&
|
|
(mode->VDisplay == pXGI->XGI_Pr->CP_VDisplay[j]) &&
|
|
(mode->type & M_T_BUILTIN))
|
|
return 0xfe;
|
|
}
|
|
}
|
|
|
|
if((pXGI->AddedPlasmaModes) && (mode->type & M_T_BUILTIN))
|
|
return 0xfe;
|
|
|
|
if((havecustommodes) &&
|
|
(pXGI->LCDwidth) && /* = test if LCD present */
|
|
(!(mode->type & M_T_DEFAULT)) &&
|
|
(!(mode->Flags & V_INTERLACE)))
|
|
return 0xfe;
|
|
|
|
if( ((mode->HDisplay <= pXGI->LCDwidth) &&
|
|
(mode->VDisplay <= pXGI->LCDheight)) ||
|
|
((pXGI->XGI_Pr->XGI_CustomT == CUT_PANEL848) &&
|
|
(((mode->HDisplay == 1360) && (mode->HDisplay == 768)) ||
|
|
((mode->HDisplay == 1024) && (mode->HDisplay == 768)) ||
|
|
((mode->HDisplay == 800) && (mode->HDisplay == 600)))) )
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
else if(VBFlags & CRT2_TV)
|
|
{ /* CRT2 is TV */
|
|
|
|
}
|
|
else if(VBFlags & CRT2_VGA)
|
|
{ /* CRT2 is VGA2 */
|
|
|
|
if((pXGI->AddedPlasmaModes) && (mode->type & M_T_BUILTIN))
|
|
return 0xfe;
|
|
|
|
if((havecustommodes) &&
|
|
(!(mode->type & M_T_DEFAULT)) &&
|
|
(!(mode->Flags & V_INTERLACE)))
|
|
return 0xfe;
|
|
|
|
}
|
|
else
|
|
{ /* CRT1 only, no CRT2 */
|
|
|
|
ModeIndex = XGI_CalcModeIndex(pScrn, mode, VBFlags, havecustommodes);
|
|
|
|
}
|
|
|
|
return(ModeIndex);
|
|
}
|
|
|
|
/* Calculate the vertical refresh rate from a mode */
|
|
int
|
|
XGICalcVRate(DisplayModePtr mode)
|
|
{
|
|
float hsync, refresh = 0;
|
|
|
|
if(mode->HSync > 0.0)
|
|
hsync = mode->HSync;
|
|
else if(mode->HTotal > 0)
|
|
hsync = (float)mode->Clock / (float)mode->HTotal;
|
|
else
|
|
hsync = 0.0;
|
|
|
|
if(mode->VTotal > 0)
|
|
refresh = hsync * 1000.0 / mode->VTotal;
|
|
|
|
if(mode->Flags & V_INTERLACE)
|
|
refresh *= 2.0;
|
|
|
|
if(mode->Flags & V_DBLSCAN)
|
|
refresh /= 2.0;
|
|
|
|
if(mode->VScan > 1)
|
|
refresh /= mode->VScan;
|
|
|
|
if(mode->VRefresh > 0.0)
|
|
refresh = mode->VRefresh;
|
|
|
|
if(hsync == 0 || refresh == 0) return(0);
|
|
|
|
return((int)(refresh));
|
|
}
|
|
|
|
/* Calculate CR33 (rate index) for CRT1.
|
|
* Calculation is done using currentmode, therefore it is
|
|
* recommended to set VertRefresh and HorizSync to correct
|
|
* values in config file.
|
|
*/
|
|
unsigned char
|
|
XGISearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|
{
|
|
/* XGIPtr pXGI = XGIPTR(pScrn); */
|
|
int i = 0;
|
|
int irefresh;
|
|
unsigned short xres = mode->HDisplay;
|
|
unsigned short yres = mode->VDisplay;
|
|
unsigned char index;
|
|
BOOLEAN checkxgi730 = FALSE;
|
|
|
|
irefresh = XGICalcVRate(mode);
|
|
if(!irefresh)
|
|
{
|
|
if(xres == 800 || xres == 1024 || xres == 1280) return 0x02;
|
|
else return 0x01;
|
|
}
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh);
|
|
#endif
|
|
|
|
/* We need the REAL refresh rate here */
|
|
if(mode->Flags & V_INTERLACE)
|
|
irefresh /= 2;
|
|
|
|
/* Do not multiply by 2 when DBLSCAN! */
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh);
|
|
#endif
|
|
|
|
index = 0;
|
|
while((xgix_vrate[i].idx != 0) && (xgix_vrate[i].xres <= xres))
|
|
{
|
|
if((xgix_vrate[i].xres == xres) && (xgix_vrate[i].yres == yres))
|
|
{
|
|
if((checkxgi730 == FALSE) || (xgix_vrate[i].XGI730valid32bpp == TRUE))
|
|
{
|
|
if(xgix_vrate[i].refresh == irefresh)
|
|
{
|
|
index = xgix_vrate[i].idx;
|
|
break;
|
|
}
|
|
else if(xgix_vrate[i].refresh > irefresh)
|
|
{
|
|
if((xgix_vrate[i].refresh - irefresh) <= 3)
|
|
{
|
|
index = xgix_vrate[i].idx;
|
|
}
|
|
else if( ((checkxgi730 == FALSE) || (xgix_vrate[i - 1].XGI730valid32bpp == TRUE)) &&
|
|
((irefresh - xgix_vrate[i - 1].refresh) <= 2) &&
|
|
(xgix_vrate[i].idx != 1) )
|
|
{
|
|
index = xgix_vrate[i - 1].idx;
|
|
}
|
|
break;
|
|
}
|
|
else if((irefresh - xgix_vrate[i].refresh) <= 2)
|
|
{
|
|
index = xgix_vrate[i].idx;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
if(index > 0)
|
|
return index;
|
|
else
|
|
{
|
|
/* Default Rate index */
|
|
if(xres == 800 || xres == 1024 || xres == 1280) return 0x02;
|
|
else return 0x01;
|
|
}
|
|
}
|
|
|
|
void
|
|
XGIWaitRetraceCRT1(ScrnInfoPtr pScrn)
|
|
{
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
int watchdog;
|
|
unsigned char temp;
|
|
|
|
inXGIIDXREG(XGICR,0x17,temp);
|
|
if(!(temp & 0x80)) return;
|
|
|
|
inXGIIDXREG(XGISR,0x1f,temp);
|
|
if(temp & 0xc0) return;
|
|
|
|
watchdog = 65536;
|
|
while((inXGIREG(XGIINPSTAT) & 0x08) && --watchdog);
|
|
watchdog = 65536;
|
|
while((!(inXGIREG(XGIINPSTAT) & 0x08)) && --watchdog);
|
|
}
|
|
|
|
static void
|
|
XGIWaitVBRetrace(ScrnInfoPtr pScrn)
|
|
{
|
|
/* XGIPtr pXGI = XGIPTR(pScrn); */
|
|
|
|
XGIWaitRetraceCRT1(pScrn);
|
|
}
|
|
|
|
#define MODEID_OFF 0x449
|
|
|
|
unsigned char
|
|
XGI_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id)
|
|
{
|
|
return(XGI_GetSetBIOSScratch(pScrn, MODEID_OFF, id));
|
|
}
|
|
|
|
unsigned char
|
|
XGI_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value)
|
|
{
|
|
unsigned char ret = 0;
|
|
#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
|
|
unsigned char *base;
|
|
|
|
base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000);
|
|
if(!base)
|
|
{
|
|
XGIErrorLog(pScrn, "(Could not map BIOS scratch area)\n");
|
|
return 0;
|
|
}
|
|
|
|
ret = *(base + offset);
|
|
|
|
/* value != 0xff means: set register */
|
|
if(value != 0xff)
|
|
*(base + offset) = value;
|
|
|
|
xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
xgiSaveUnlockExtRegisterLock(XGIPtr pXGI, unsigned char *reg1, unsigned char *reg2)
|
|
{
|
|
register unsigned char val;
|
|
unsigned long mylockcalls;
|
|
|
|
pXGI->lockcalls++;
|
|
mylockcalls = pXGI->lockcalls;
|
|
|
|
/* check if already unlocked */
|
|
inXGIIDXREG(XGISR, 0x05, val);
|
|
if(val != 0xa1)
|
|
{
|
|
/* save State */
|
|
if(reg1) *reg1 = val;
|
|
/* unlock */
|
|
/*
|
|
outb (0x3c4, 0x20);
|
|
val4 = inb (0x3c5);
|
|
val4 |= 0x20;
|
|
outb (0x3c5, val4);
|
|
*/
|
|
outXGIIDXREG(XGISR, 0x05, 0x86);
|
|
inXGIIDXREG(XGISR, 0x05, val);
|
|
if(val != 0xA1)
|
|
{
|
|
#ifdef TWDEBUG
|
|
unsigned char val1, val2;
|
|
int i;
|
|
#endif
|
|
XGIErrorLog(pXGI->pScrn,
|
|
"Failed to unlock sr registers (%p, %lx, 0x%02x; %ld)\n",
|
|
(void *)pXGI, (unsigned long)pXGI->RelIO, val, mylockcalls);
|
|
#ifdef TWDEBUG
|
|
for(i = 0; i <= 0x3f; i++)
|
|
{
|
|
inXGIIDXREG(XGISR, i, val1);
|
|
inXGIIDXREG(0x3c4, i, val2);
|
|
xf86DrvMsg(pXGI->pScrn->scrnIndex, X_INFO,
|
|
"SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%d)\n",
|
|
i, val1, val2, mylockcalls);
|
|
}
|
|
#endif
|
|
if((pXGI->VGAEngine == XGI_OLD_VGA) || (pXGI->VGAEngine == XGI_530_VGA))
|
|
{
|
|
/* Emergency measure: unlock at 0x3c4, and try to enable Relocated IO ports */
|
|
outXGIIDXREG(0x3c4,0x05,0x86);
|
|
andXGIIDXREG(0x3c4,0x33,~0x20);
|
|
outXGIIDXREG(XGISR, 0x05, 0x86);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
if((pXGI->VGAEngine == XGI_OLD_VGA) || (pXGI->VGAEngine == XGI_530_VGA))
|
|
{
|
|
inXGIIDXREG(XGICR, 0x80, val);
|
|
if(val != 0xa1)
|
|
{
|
|
/ * save State * /
|
|
if(reg2) *reg2 = val;
|
|
outXGIIDXREG(XGICR, 0x80, 0x86);
|
|
inXGIIDXREG(XGICR, 0x80, val);
|
|
if(val != 0xA1)
|
|
{
|
|
XGIErrorLog(pXGI->pScrn,
|
|
"Failed to unlock cr registers (%p, %lx, 0x%02x)\n",
|
|
(void *)pXGI, (unsigned long)pXGI->RelIO, val);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void
|
|
xgiRestoreExtRegisterLock(XGIPtr pXGI, unsigned char reg1, unsigned char reg2)
|
|
{
|
|
/* restore lock */
|
|
#ifndef UNLOCK_ALWAYS
|
|
outXGIIDXREG(XGISR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00);
|
|
if((pXGI->VGAEngine == XGI_OLD_VGA) || (pXGI->VGAEngine == XGI_530_VGA))
|
|
{
|
|
outXGIIDXREG(XGICR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
/* The select system call can not be used under X driver, don't know why. */
|
|
void
|
|
DelayS(int sec)
|
|
{
|
|
/* delay seconds */
|
|
struct timeval delay ;
|
|
|
|
delay.tv_sec = sec ;
|
|
delay.tv_usec = 0 ;
|
|
select(0, NULL, NULL, NULL, &delay);
|
|
}
|
|
|
|
void
|
|
DelayMS(int ms)
|
|
{
|
|
/* delay milliseconds */
|
|
struct timeval delay ;
|
|
|
|
delay.tv_sec = ms / 1000 ;
|
|
delay.tv_usec = (ms % 1000)*1000 ;
|
|
select(0, NULL, NULL, NULL, &delay);
|
|
}
|
|
|
|
void
|
|
DelayUS(int us)
|
|
{
|
|
/* delay microseconds */
|
|
struct timeval delay ;
|
|
|
|
delay.tv_sec = us / 1000000 ;
|
|
delay.tv_usec = us % 1000000 ;
|
|
select(0, NULL, NULL, NULL, &delay);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
XGIDumpSR(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("SR xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x40 ; i+=0x10 )
|
|
{
|
|
ErrorF("SR[%02X]:",i) ;
|
|
for(j =0 ; j < 16 ; j++)
|
|
{
|
|
inXGIIDXREG(XGISR,(i+j), temp ) ;
|
|
ErrorF(" %02lX",temp) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
ErrorF( "\n" ) ;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
XGIDumpCR(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("CR xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x100 ; i+=0x10 )
|
|
{
|
|
ErrorF("CR[%02X]:",i) ;
|
|
for(j =0 ; j < 16 ; j++)
|
|
{
|
|
inXGIIDXREG(XGICR,(i+j), temp ) ;
|
|
ErrorF(" %02lX",temp) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpGR(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("GR xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("GR:") ;
|
|
for( i = 0 ; i < 0x9 ; i+=0x10 )
|
|
{
|
|
inXGIIDXREG(XGISR,i, temp ) ;
|
|
ErrorF(" %02lX",temp);
|
|
}
|
|
ErrorF("\n") ;
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
|
|
void
|
|
XGIDumpPart0(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART0 xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x50 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART0[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART0,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpPart05(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART05 xx\n");
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x50 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART05[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART05,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpPart1(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART1 xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x100 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART1[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART1,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpPart2(ScrnInfoPtr pScrn)
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART2 xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x100 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART2[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART2,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpPart3(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART3 xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
|
|
for( i = 0 ; i < 0x100 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART3[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART3,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpPart4(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("PART4 xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0x100 ; i+=0x10 )
|
|
{
|
|
ErrorF("PART4[%02X]:", i) ;
|
|
for( j = 0 ; j < 0x10 ; j++)
|
|
{
|
|
inXGIIDXREG(XGIPART4,(i+j),temp ) ;
|
|
ErrorF(" %02lX", temp ) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpMMIO(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i ;
|
|
unsigned long temp ;
|
|
/*
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("MMIO 85xx\n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0x8500 ; i < 0x8600 ; i+=0x10 )
|
|
{
|
|
ErrorF("[%04X]: %08lX %08lX %08lX %08lX\n",i,
|
|
XGIMMIOLONG(i),
|
|
XGIMMIOLONG(i+4),
|
|
XGIMMIOLONG(i+8),
|
|
XGIMMIOLONG(i+12)) ;
|
|
}
|
|
*/
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
void
|
|
XGIDumpRegs(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
XGIDumpSR(pScrn);
|
|
XGIDumpCR(pScrn);
|
|
// XGIDumpGR(pScrn);
|
|
// XGIDumpPalette(pScrn);
|
|
XGIDumpMMIO(pScrn);
|
|
if( pXGI->Chipset != PCI_CHIP_XGIXG20 )
|
|
{
|
|
XGIDumpPart0(pScrn);
|
|
XGIDumpPart05(pScrn);
|
|
XGIDumpPart1(pScrn);
|
|
XGIDumpPart2(pScrn);
|
|
XGIDumpPart3(pScrn);
|
|
XGIDumpPart4(pScrn);
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
int
|
|
DumpDDIName(const char *fmt, ...)
|
|
{
|
|
#ifdef DUMPDDI
|
|
static char buff[0x1000] ;
|
|
va_list argptr ;
|
|
va_start(argptr, fmt) ;
|
|
vsprintf(buff,fmt,argptr) ;
|
|
va_end(argptr) ;
|
|
|
|
ErrorF(buff) ;
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
XGIDumpPalette(ScrnInfoPtr pScrn)
|
|
{
|
|
#ifdef DEBUG
|
|
XGIPtr pXGI = XGIPTR(pScrn);
|
|
|
|
int i,j ;
|
|
unsigned long temp ;
|
|
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
ErrorF("Palette \n") ;
|
|
ErrorF("----------------------------------------------------------------------\n") ;
|
|
for( i = 0 ; i < 0xFF ; i+=0x04 )
|
|
{
|
|
|
|
for(j =0 ; j < 16 ; j++)
|
|
{
|
|
ErrorF("PA[%02X]:",i+j) ;
|
|
outb(0x3c7,i+j);
|
|
temp=inb(0x3c9);
|
|
ErrorF(" %02lX",temp) ;
|
|
temp=inb(0x3c9);
|
|
ErrorF(" %02lX",temp) ;
|
|
temp=inb(0x3c9);
|
|
ErrorF(" %02lX",temp) ;
|
|
}
|
|
ErrorF("\n") ;
|
|
}
|
|
ErrorF( "\n" ) ;
|
|
#endif
|
|
}
|
|
|