/* * Copyright 1992-2003 by Alan Hourihane, North Wales, UK. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Alan Hourihane not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Alan Hourihane makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Alan Hourihane, alanh@fairlite.demon.co.uk * Re-written for XFree86 v4.0 * * Previous driver (pre-XFree86 v4.0) by * Alan Hourihane, alanh@fairlite.demon.co.uk * David Wexelblat (major contributor) * Massimiliano Ghilardi, max@Linuz.sns.it, some fixes to the * clockchip programming code. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "fb.h" #include "micmap.h" #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Pci.h" #include "xf86cmap.h" #include "vgaHW.h" #include "vbe.h" #include "dixstruct.h" #include "compiler.h" #include "mipointer.h" #include "shadow.h" #include "trident.h" #include "trident_regs.h" #ifdef XFreeXDGA #define _XF86DGA_SERVER_ #include #endif #include "globals.h" #ifdef HAVE_XEXTPROTO_71 #include #else #define DPMS_SERVER #include #endif #include "xf86xv.h" static const OptionInfoRec * TRIDENTAvailableOptions(int chipid, int busid); static void TRIDENTIdentify(int flags); static Bool TRIDENTProbe(DriverPtr drv, int flags); static Bool TRIDENTPreInit(ScrnInfoPtr pScrn, int flags); static Bool TRIDENTScreenInit(SCREEN_INIT_ARGS_DECL); /* * This is intentionally screen-independent. It indicates the binding * choice made in the first PreInit. */ static int pix24bpp = 0; #define TRIDENT_VERSION 4000 #define TRIDENT_NAME "TRIDENT" #define TRIDENT_DRIVER_NAME "trident" #define TRIDENT_MAJOR_VERSION PACKAGE_VERSION_MAJOR #define TRIDENT_MINOR_VERSION PACKAGE_VERSION_MINOR #define TRIDENT_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL /* * 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. */ _X_EXPORT DriverRec TRIDENT = { TRIDENT_VERSION, TRIDENT_DRIVER_NAME, TRIDENTIdentify, TRIDENTProbe, TRIDENTAvailableOptions, NULL, 0 }; static SymTabRec TRIDENTChipsets[] = { { TVGA9000, "tvga9000" }, { TVGA9000i, "tvga9000i" }, { TVGA8900C, "tvga8900c" }, { TVGA8900D, "tvga8900d" }, { TVGA9200CXr, "tvga9200cxr" }, { TGUI9400CXi, "tgui9400cxi" }, { CYBER9320, "cyber9320" }, { CYBER9388, "cyber9388" }, { CYBER9397, "cyber9397" }, { CYBER9397DVD, "cyber9397dvd" }, { CYBER9520, "cyber9520" }, { CYBER9525DVD, "cyber9525dvd" }, { CYBERBLADEE4, "cyberblade/e4" }, { TGUI9420DGi, "tgui9420dgi" }, { TGUI9440AGi, "tgui9440agi" }, { TGUI9660, "tgui9660" }, { TGUI9680, "tgui9680" }, { PROVIDIA9682, "providia9682" }, { PROVIDIA9685, "providia9685" }, { CYBER9382, "cyber9382" }, { CYBER9385, "cyber9385" }, { IMAGE975, "3dimage975" }, { IMAGE985, "3dimage985" }, { BLADE3D, "blade3d" }, { CYBERBLADEI7, "cyberbladei7" }, { CYBERBLADEI7D, "cyberbladei7d" }, { CYBERBLADEI1, "cyberbladei1" }, { CYBERBLADEI1D, "cyberbladei1d" }, { CYBERBLADEAI1, "cyberbladeAi1" }, { CYBERBLADEAI1D, "cyberbladeAi1d" }, { BLADEXP, "bladeXP" }, { CYBERBLADEXPAI1, "cyberbladeXPAi1" }, { CYBERBLADEXP4, "cyberbladeXP4" }, { XP5, "XP5" }, { -1, NULL } }; static PciChipsets TRIDENTPciChipsets[] = { { CYBER9320, PCI_CHIP_9320, RES_SHARED_VGA }, { CYBER9388, PCI_CHIP_9388, RES_SHARED_VGA }, { CYBER9397, PCI_CHIP_9397, RES_SHARED_VGA }, { CYBER9397DVD, PCI_CHIP_939A, RES_SHARED_VGA }, { CYBER9520, PCI_CHIP_9520, RES_SHARED_VGA }, { CYBER9525DVD, PCI_CHIP_9525, RES_SHARED_VGA }, { CYBERBLADEE4, PCI_CHIP_9540, RES_SHARED_VGA }, { TGUI9420DGi, PCI_CHIP_9420, RES_SHARED_VGA }, { TGUI9440AGi, PCI_CHIP_9440, RES_SHARED_VGA }, { TGUI9660, PCI_CHIP_9660, RES_SHARED_VGA }, { TGUI9680, PCI_CHIP_9660, RES_SHARED_VGA }, { PROVIDIA9682, PCI_CHIP_9660, RES_SHARED_VGA }, { PROVIDIA9685, PCI_CHIP_9660, RES_SHARED_VGA }, { CYBER9382, PCI_CHIP_9660, RES_SHARED_VGA }, { CYBER9385, PCI_CHIP_9660, RES_SHARED_VGA }, { IMAGE975, PCI_CHIP_9750, RES_SHARED_VGA }, { IMAGE985, PCI_CHIP_9850, RES_SHARED_VGA }, { BLADE3D, PCI_CHIP_9880, RES_SHARED_VGA }, { CYBERBLADEI7, PCI_CHIP_8400, RES_SHARED_VGA }, { CYBERBLADEI7D, PCI_CHIP_8420, RES_SHARED_VGA }, { CYBERBLADEI1, PCI_CHIP_8500, RES_SHARED_VGA }, { CYBERBLADEI1D, PCI_CHIP_8520, RES_SHARED_VGA }, { CYBERBLADEAI1, PCI_CHIP_8600, RES_SHARED_VGA }, { CYBERBLADEAI1D, PCI_CHIP_8620, RES_SHARED_VGA }, { BLADEXP, PCI_CHIP_9910, RES_SHARED_VGA }, { CYBERBLADEXPAI1, PCI_CHIP_8820, RES_SHARED_VGA }, { CYBERBLADEXP4, PCI_CHIP_2100, RES_SHARED_VGA }, { XP5, PCI_CHIP_2200, RES_SHARED_VGA }, { -1, -1, RES_UNDEFINED } }; typedef enum { OPTION_ACCELMETHOD, OPTION_SW_CURSOR, OPTION_PCI_RETRY, OPTION_RGB_BITS, OPTION_NOACCEL, OPTION_SETMCLK, OPTION_MUX_THRESHOLD, OPTION_SHADOW_FB, OPTION_ROTATE, OPTION_MMIO_ONLY, OPTION_VIDEO_KEY, OPTION_NOMMIO, OPTION_NOPCIBURST, OPTION_CYBER_SHADOW, OPTION_CYBER_STRETCH, OPTION_XV_HSYNC, OPTION_XV_VSYNC, OPTION_XV_BSKEW, OPTION_XV_RSKEW, OPTION_FP_DELAY, OPTION_1400_DISPLAY, OPTION_DISPLAY, OPTION_GB, OPTION_TV_CHIPSET, OPTION_TV_SIGNALMODE } TRIDENTOpts; static const OptionInfoRec TRIDENTOptions[] = { { OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SETMCLK, "SetMClk", OPTV_FREQ, {0}, FALSE }, { OPTION_MUX_THRESHOLD, "MUXThreshold", OPTV_INTEGER, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_NOMMIO, "NoMMIO", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOPCIBURST, "NoPciBurst", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MMIO_ONLY, "MMIOonly", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CYBER_SHADOW, "CyberShadow", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CYBER_STRETCH, "CyberStretch", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XV_HSYNC, "XvHsync", OPTV_INTEGER, {0}, FALSE }, { OPTION_XV_VSYNC, "XvVsync", OPTV_INTEGER, {0}, FALSE }, { OPTION_XV_BSKEW, "XvBskew", OPTV_INTEGER, {0}, FALSE }, { OPTION_XV_RSKEW, "XvRskew", OPTV_INTEGER, {0}, FALSE }, { OPTION_FP_DELAY, "FpDelay", OPTV_INTEGER, {0}, FALSE }, { OPTION_1400_DISPLAY, "Display1400", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DISPLAY, "Display", OPTV_ANYSTR, {0}, FALSE }, { OPTION_GB, "GammaBrightness", OPTV_ANYSTR, {0}, FALSE }, { OPTION_TV_CHIPSET, "TVChipset", OPTV_ANYSTR, {0}, FALSE }, { OPTION_TV_SIGNALMODE, "TVSignal", OPTV_INTEGER, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; /* Clock Limits */ static int ClockLimit[] = { 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 80000, 90000, 90000, 135000, 135000, 170000, 170000, 170000, 170000, 170000, 170000, 170000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, }; static int ClockLimit16bpp[] = { 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 40000, 45000, 45000, 90000, 90000, 135000, 135000, 170000, 170000, 170000, 170000, 170000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, 230000, }; static int ClockLimit24bpp[] = { 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 40000, 40000, 70000, 70000, 70000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, }; static int ClockLimit32bpp[] = { 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 25180, 40000, 40000, 70000, 70000, 70000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, 115000, }; /* * These are fixed modelines for all physical display dimensions the * chipsets supports on FPs. Most of them are not tested yet. */ #if 0 tridentLCD LCD[] = { /* 0 3 4 5 6 7 10 11 16 */ { 0,"640x480",25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08}, { 1,"800x600",40000,0x7f,0x99,0x69,0x99,0x72,0xf0,0x59,0x2d,0x5e,0x08}, { 2,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, { 3,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, /*0x96*/ { 4,"1280x1024",108000,0xa3,0x6,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, { 5,"1024x600",50500 ,0xa3,0x6,0x8f,0xa0,0xb,0x3e,0xea,0x8c,0xb,0x08}, { 0xff,"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; #else #if 0 tridentLCD LCD[] = { { 1,640,480,25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08}, { 3,800,600,40000,0x7f,0x82,0x6b,0x1b,0x72,0xf8,0x58,0x8c,0x72,0x08}, { 2,1024,768,65000,0xa3,/*0x6*/0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x24,0x0a,0x08}, { 0,1280,1024,108000,0xce,0x81,0xa6,0x9a,0x27,0x50,0x00,0x03,0x26,0xa8}, { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; #else tridentLCD LCD[] = { { 1,640,480,25200,0x5f,0x80,0x52,0x1e,0xb,0x3e,0xea,0x0c,0xb,0x08}, { 3,800,600,40000,0x7f,0x00,0x69,0x7f,0x72,0xf0,0x59,0x0d,0x00,0x08}, { 2,1024,768,65000,0xa3,0x00,0x84,0x94,0x24,0xf5,0x03,0x09,0x24,0x08}, { 0,1280,1024,108000,0xce,0x91,0xa6,0x14,0x28,0x5a,0x01,0x04,0x28,0xa8}, { 4,1400,1050,122000,0xe6,0x8d,0xba,0x1d,0x38,0x00,0x1c,0x28,0x28,0xf8}, { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; #endif #endif #ifdef XFree86LOADER static MODULESETUPPROTO(tridentSetup); static XF86ModuleVersionInfo tridentVersRec = { "trident", MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, TRIDENT_MAJOR_VERSION, TRIDENT_MINOR_VERSION, TRIDENT_PATCHLEVEL, ABI_CLASS_VIDEODRV, /* This is a video driver */ ABI_VIDEODRV_VERSION, MOD_CLASS_VIDEODRV, {0,0,0,0} }; _X_EXPORT XF86ModuleData tridentModuleData = { &tridentVersRec, tridentSetup, NULL }; pointer tridentSetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; if (!setupDone) { setupDone = TRUE; xf86AddDriver(&TRIDENT, module, 0); return (pointer)TRUE; } if (errmaj) *errmaj = LDR_ONCEONLY; return NULL; } #endif /* XFree86LOADER */ static void TRIDENTEnableMMIO(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); unsigned long vgaIOBase = pTrident->PIOBase + VGAHWPTR(pScrn)->IOBase; CARD8 temp = 0, protect = 0; /* Goto New Mode */ outb(pTrident->PIOBase + 0x3C4, 0x0B); inb(pTrident->PIOBase + 0x3C5); /* Unprotect registers */ if (pTrident->Chipset > PROVIDIA9685) { outb(pTrident->PIOBase + 0x3C4, Protection); protect = inb(pTrident->PIOBase + 0x3C5); outb(pTrident->PIOBase + 0x3C5, 0x92); } outb(pTrident->PIOBase + 0x3C4, NewMode1); temp = inb(pTrident->PIOBase + 0x3C5); outb(pTrident->PIOBase + 0x3C5, 0x80); /* Enable MMIO */ outb(vgaIOBase + 4, PCIReg); pTrident->REGPCIReg = inb(vgaIOBase + 5); outb(vgaIOBase + 5, pTrident->REGPCIReg | 0x01); /* Enable it */ /* Protect registers */ if (pTrident->Chipset > PROVIDIA9685) { OUTB(0x3C4, Protection); OUTB(0x3C5, protect); } OUTB(0x3C4, NewMode1); OUTB(0x3C5, temp); } static void TRIDENTDisableMMIO(ScrnInfoPtr pScrn) { int vgaIOBase = VGAHWPTR(pScrn)->IOBase; CARD8 temp = 0, protect = 0; TRIDENTPtr pTrident = TRIDENTPTR(pScrn); /* Goto New Mode */ OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Unprotect registers */ OUTB(0x3C4, NewMode1); temp = INB(0x3C5); OUTB(0x3C5, 0x80); if (pTrident->Chipset > PROVIDIA9685) { OUTB(0x3C4, Protection); protect = INB(0x3C5); OUTB(0x3C5, 0x92); } /* Disable MMIO access */ OUTB(vgaIOBase + 4, PCIReg); pTrident->REGPCIReg = INB(vgaIOBase + 5); OUTB(vgaIOBase + 5, pTrident->REGPCIReg & 0xFE); /* Protect registers */ if (pTrident->Chipset > PROVIDIA9685) { outb(pTrident->PIOBase + 0x3C4, Protection); outb(pTrident->PIOBase + 0x3C5, protect); } outb(pTrident->PIOBase + 0x3C4, NewMode1); outb(pTrident->PIOBase + 0x3C5, temp); } /* * This is a terrible hack! If we are on a notebook in a stretched * mode and don't want full screen we use the BIOS to set an unstreched * mode. */ void tridentSetModeBIOS(ScrnInfoPtr pScrn, DisplayModePtr mode) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); #ifdef VBE_INFO if (pTrident->vbeModes) { vbeSaveRestoreRec vbesr; vbesr.stateMode = VBECalcVbeModeIndex(pTrident->vbeModes, mode, pScrn->bitsPerPixel); vbesr.pstate = NULL; if (vbesr.stateMode) { if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); VBEVesaSaveRestore(pTrident->pVbe,&vbesr,MODE_RESTORE); if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn); return; } else xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"No BIOS Mode matches " "%ix%I@%ibpp\n",mode->HDisplay,mode->VDisplay, pScrn->bitsPerPixel); } #endif /* This function is only for LCD screens, and also when we have * int10 available */ if (pTrident->IsCyber && pTrident->lcdMode && pTrident->Int10) { int i = pTrident->lcdMode; if ((pScrn->currentMode->HDisplay != LCD[i].display_x) /* !fullsize? */ || (pScrn->currentMode->VDisplay != LCD[i].display_y)) { if (pTrident->lcdActive) { /* LCD Active ?*/ int h_str, v_str; OUTB(0x3CE,HorStretch); h_str = INB(0x3CF) & 0x01; OUTB(0x3CE,VertStretch); v_str = INB(0x3CF) & 0x01; if (h_str || v_str) { OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92); OUTW(0x3CE, BiosReg ); pTrident->Int10->ax = 0x3; pTrident->Int10->num = 0x10; if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); xf86ExecX86int10(pTrident->Int10); if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn); } } } } } /* Currently we only test for 1400 */ static int TRIDENTLcdDisplaySize (xf86MonPtr pMon) { if (pMon) { int i,j; for (i = 0; i < STD_TIMINGS; i++) { if (pMon->timings2[i].hsize == 1400) { return 1400; } } /* * If not explicitly set try to find out if the display supports * the 1400 mode. For sanity check if DDC comes from a digital * display. */ if (DIGITAL(pMon->features.input_type)) { for (i = 0; i < DET_TIMINGS; i++) { if (pMon->det_mon[i].type == DS_STD_TIMINGS) { for (j = 0; j < 5; j++) { if (pMon->det_mon[i].section.std_t[j].hsize == 1400) { return 1400; } } } else if (pMon->det_mon[i].type == DT) { if (pMon->det_mon[i].section.d_timings.h_active == 1400) { return 1400; } } } } } return 0; } /* * Initialise a new mode. This is currently still using the old * "initialise struct, restore/write struct to HW" model. That could * be changed. */ static Bool TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg; TRIDENTPtr pTrident = TRIDENTPTR(pScrn); TRIDENTRegPtr tridentReg; WAITFORVSYNC; TridentFindClock(pScrn,mode->Clock); switch (pTrident->Chipset) { case TGUI9660: case TGUI9680: case PROVIDIA9682: case PROVIDIA9685: case IMAGE975: case IMAGE985: case BLADE3D: case CYBERBLADEI7: case CYBERBLADEI7D: case CYBERBLADEI1: case CYBERBLADEI1D: case CYBERBLADEAI1: case CYBERBLADEAI1D: case CYBER9520: case CYBER9525DVD: case CYBERBLADEE4: case CYBER9397: case CYBER9397DVD: case BLADEXP: case CYBERBLADEXPAI1: case CYBERBLADEXP4: case XP5: /* Get ready for MUX mode */ if (pTrident->MUX && pScrn->bitsPerPixel == 8 && !mode->CrtcHAdjusted) { ErrorF("BARF\n"); mode->CrtcHDisplay >>= 1; mode->CrtcHSyncStart >>= 1; mode->CrtcHSyncEnd >>= 1; mode->CrtcHBlankStart >>= 1; mode->CrtcHBlankEnd >>= 1; mode->CrtcHTotal >>= 1; mode->CrtcHAdjusted = TRUE; } break; default: if (pScrn->videoRam < 1024 && !mode->CrtcHAdjusted) { mode->CrtcHDisplay <<= 1; mode->CrtcHSyncStart <<= 1; mode->CrtcHSyncEnd <<= 1; mode->CrtcHBlankStart <<= 1; mode->CrtcHBlankEnd <<= 1; mode->CrtcHTotal <<= 1; mode->CrtcHAdjusted = TRUE; } break; } vgaHWUnlock(hwp); /* Initialise the ModeReg values */ if (!vgaHWInit(pScrn, mode)) return FALSE; pScrn->vtSema = TRUE; /* * We used to do this at a later time. * Now since READOUT isn't defined any more * we do it here. * The original NOTE read: * TridentInit() has to modify registers * that have already been set by vgaHWRestore(). * So we call it _after_ vgaHWRestore() has * programmed these registers. */ if (pScrn->progClock) { if (!TridentInit(pScrn, mode)) return FALSE; } else { if (!TVGAInit(pScrn, mode)) return FALSE; } /* Program the registers */ vgaHWProtect(pScrn, TRUE); vgaReg = &hwp->ModeReg; tridentReg = &pTrident->ModeReg; vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); if (pScrn->progClock) TridentRestore(pScrn, tridentReg); else TVGARestore(pScrn, tridentReg); vgaHWProtect(pScrn, FALSE); if (pTrident->TVChipset != 0) VIA_TVInit(pScrn); return TRUE; } static Bool TRIDENTGetRec(ScrnInfoPtr pScrn) { /* * Allocate an TRIDENTRec, 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 = XNFcallocarray(sizeof(TRIDENTRec), 1); /* Initialise it */ return TRUE; } static void TRIDENTFreeRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate == NULL) return; free(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } /* * This function saves the video state. */ static void TRIDENTSave(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident; vgaRegPtr vgaReg; TRIDENTRegPtr tridentReg; pTrident = TRIDENTPTR(pScrn); vgaReg = &VGAHWPTR(pScrn)->SavedReg; tridentReg = &pTrident->SavedReg; vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP | (IsPrimaryCard ? VGA_SR_FONTS : 0)); if (pScrn->progClock) TridentSave(pScrn, tridentReg); else TVGASave(pScrn, tridentReg); if (pTrident->TVChipset != 0) VIA_SaveTVDepentVGAReg(pScrn); } /* * Restore the initial (text) mode. */ static void TRIDENTRestore(ScrnInfoPtr pScrn) { vgaHWPtr hwp; vgaRegPtr vgaReg; TRIDENTPtr pTrident; TRIDENTRegPtr tridentReg; hwp = VGAHWPTR(pScrn); pTrident = TRIDENTPTR(pScrn); vgaReg = &hwp->SavedReg; tridentReg = &pTrident->SavedReg; vgaHWProtect(pScrn, TRUE); if (pScrn->progClock) TridentRestore(pScrn, tridentReg); else TVGARestore(pScrn, tridentReg); vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP | (IsPrimaryCard ? VGA_SR_FONTS : 0)); if (pTrident->TVChipset != 0) VIA_RestoreTVDependVGAReg(pScrn); vgaHWProtect(pScrn, FALSE); } /* Usually mandatory */ Bool TRIDENTSwitchMode(SWITCH_MODE_ARGS_DECL) { SCRN_INFO_PTR(arg); return TRIDENTModeInit(pScrn, mode); } /* * This function is used to initialize the Start Address - the first * displayed location in the video memory. */ /* Usually mandatory */ void TRIDENTAdjustFrame(ADJUST_FRAME_ARGS_DECL) { SCRN_INFO_PTR(arg); TRIDENTPtr pTrident; int base = y * pScrn->displayWidth + x; int vgaIOBase; CARD8 temp; pTrident = TRIDENTPTR(pScrn); vgaIOBase = VGAHWPTR(pScrn)->IOBase; switch (pScrn->bitsPerPixel) { case 8: if (pScrn->progClock) base = (base & 0xFFFFFFF8) >> 2; else base = (base & 0xFFFFFFF8) >> 3; break; case 16: base >>= 1; break; case 24: base = (((base + 1) & ~0x03) * 3) >> 2; break; case 32: break; } /* CRT bits 0-15 */ OUTW(vgaIOBase + 4, (base & 0x00FF00) | 0x0C); OUTW(vgaIOBase + 4, ((base & 0x00FF) << 8) | 0x0D); /* CRT bit 16 */ OUTB(vgaIOBase + 4, CRTCModuleTest); temp = INB(vgaIOBase + 5) & 0xDF; OUTB(vgaIOBase + 5, temp | ((base & 0x10000) >> 11)); /* CRT bit 17-19 */ OUTB(vgaIOBase + 4, CRTHiOrd); temp = INB(vgaIOBase + 5) & 0xF8; OUTB(vgaIOBase + 5, temp | ((base & 0xE0000) >> 17)); } /* * This is called when VT switching back to the X server. Its job is * to reinitialise the video mode. */ /* Mandatory */ static Bool TRIDENTEnterVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn); /* Should we re-save the text mode on each VT enter? */ if (!TRIDENTModeInit(pScrn, pScrn->currentMode)) return FALSE; if (pTrident->InitializeAccelerator) pTrident->InitializeAccelerator(pScrn); return TRUE; } /* * This is called when VT switching away from the X server. Its job is * to restore the previous (text) mode. * * We may wish to remap video/MMIO memory too. */ /* Mandatory */ static void TRIDENTLeaveVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); if (!pTrident->NoAccel && pTrident->useEXA) pTrident->EXADriverPtr->WaitMarker(pScrn->pScreen, 0); TRIDENTRestore(pScrn); vgaHWLock(hwp); if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); } /* Free up any per-generation data structures */ /* Optional */ static void TRIDENTFreeScreen(FREE_SCREEN_ARGS_DECL) { SCRN_INFO_PTR(arg); if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); TRIDENTFreeRec(pScrn); } /* Checks if a mode is suitable for the selected chipset. */ /* Optional */ static ModeStatus TRIDENTValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) { SCRN_INFO_PTR(arg); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); if (pTrident->lcdActive && (pTrident->lcdMode != 0xff)){ if (((mode->HDisplay > LCD[pTrident->lcdMode].display_x) || (mode->VDisplay > LCD[pTrident->lcdMode].display_y))) { xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Removing mode (%dx%d) " "larger than the LCD panel (%dx%d)\n", mode->HDisplay, mode->VDisplay, LCD[pTrident->lcdMode].display_x, LCD[pTrident->lcdMode].display_y); return(MODE_BAD); } if (((float)mode->HDisplay/(float)mode->VDisplay) > 2.0) { xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Removing mode (%dx%d) " "unusual aspect ratio\n", mode->HDisplay, mode->VDisplay); return(MODE_BAD); } } return (MODE_OK); } static void TRIDENTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); CARD8 DPMSCont, PMCont, temp; if (!pScrn->vtSema) return; OUTB(0x3C4, 0x0E); temp = INB(0x3C5); OUTB(0x3C5, 0xC2); OUTB(0x83C8, 0x04); /* Read DPMS Control */ PMCont = INB(0x83C6) & 0xFC; OUTB(0x3CE, 0x23); DPMSCont = INB(0x3CF) & 0xFC; switch (PowerManagementMode) { case DPMSModeOn: /* Screen: On, HSync: On, VSync: On */ PMCont |= 0x03; DPMSCont |= 0x00; break; case DPMSModeStandby: /* Screen: Off, HSync: Off, VSync: On */ PMCont |= 0x02; DPMSCont |= 0x01; break; case DPMSModeSuspend: /* Screen: Off, HSync: On, VSync: Off */ PMCont |= 0x02; DPMSCont |= 0x02; break; case DPMSModeOff: /* Screen: Off, HSync: Off, VSync: Off */ PMCont |= 0x00; DPMSCont |= 0x03; break; } OUTB(0x3CF, DPMSCont); OUTB(0x83C8, 0x04); OUTB(0x83C6, PMCont); OUTW(0x3C4, (temp<<8) | 0x0E); } static void TRIDENTBlockHandler (BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); pScreen->BlockHandler = pTrident->BlockHandler; (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); pScreen->BlockHandler = TRIDENTBlockHandler; if(pTrident->VideoTimerCallback) { UpdateCurrentTime(); (*pTrident->VideoTimerCallback)(pScrn, currentTime.milliseconds); } } static const OptionInfoRec * TRIDENTAvailableOptions(int chipid, int busid) { return TRIDENTOptions; } /* Mandatory */ static void TRIDENTIdentify(int flags) { xf86PrintChipsets(TRIDENT_NAME, "driver for Trident chipsets", TRIDENTChipsets); } Bool TRIDENTClockSelect(ScrnInfoPtr pScrn, int no) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); unsigned char temp; /* * CS0 and CS1 are in MiscOutReg * * For 8900B, 8900C, 8900CL and 9000, CS2 is bit 0 of * New Mode Control Register 2. * * For 8900CL, CS3 is bit 4 of Old Mode Control Register 1. * * For 9000, CS3 is bit 6 of New Mode Control Register 2. * * For TGUI, we don't use the ClockSelect function at all. */ switch(no) { case CLK_REG_SAVE: pTrident->SaveClock1 = INB(0x3CC); if (pTrident->Chipset != TVGA8800CS) { if ( (pScrn->numClocks == 16) && (pTrident->Chipset != TVGA9000) && (pTrident->Chipset != TVGA9000i) ) { OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ OUTB(0x3C4, 0x0E); pTrident->SaveClock3 = INB(0x3C5); } OUTB(0x3C4, 0x0B); INB(0x3C5); /* Now to New Mode */ OUTB(0x3C4, 0x0D); pTrident->SaveClock2 = INB(0x3C5); } break; case CLK_REG_RESTORE: OUTB(0x3C2, pTrident->SaveClock1); if (pTrident->Chipset != TVGA8800CS) { if ( (pScrn->numClocks == 16) && (pTrident->Chipset != TVGA9000) && (pTrident->Chipset != TVGA9000i) ) { OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ OUTW(0x3C4, (pTrident->SaveClock3 << 8) | 0x0E); } OUTB(0x3C4, 0x0B); INB(0x3C5); /* Now to New Mode */ OUTW(0x3C4, (pTrident->SaveClock2 << 8) | 0x0D); } break; default: /* * Do CS0 and CS1 */ temp = INB(0x3CC); OUTB(0x3C2, (temp & 0xF3) | ((no << 2) & 0x0C)); if (pTrident->Chipset != TVGA8800CS) { if ( (pScrn->numClocks == 16) && (pTrident->Chipset != TVGA9000) && (pTrident->Chipset != TVGA9000i) ) { /* * Go to Old Mode for CS3. */ OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ OUTB(0x3C4, 0x0E); temp = INB(0x3C5) & 0xEF; temp |= (no & 0x08) << 1; OUTB(0x3C5, temp); } /* * Go to New Mode for CS2 and TVGA9000 CS3. */ OUTB(0x3C4, 0x0B); INB(0x3C5); /* Now to New Mode */ OUTB(0x3C4, 0x0D); /* * Bits 1 & 2 are dividers - set to 0 to get no * clock division. */ temp = INB(0x3C5) & 0xF8; temp |= (no & 0x04) >> 2; if ( (pTrident->Chipset == TVGA9000) || (pTrident->Chipset == TVGA9000i) ) { temp &= ~0x40; temp |= (no & 0x08) << 3; } OUTB(0x3C5, temp); } } return(TRUE); } /* * Map the framebuffer and MMIO memory. */ static Bool TRIDENTMapMem(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); int mapsize = 0x10000; if (Is3Dchip) mapsize = 0x20000; if (IsPciCard && UseMMIO) #ifndef XSERVER_LIBPCIACCESS pTrident->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pTrident->PciTag, pTrident->IOAddress, mapsize); #else { void **result = (void **)&pTrident->IOBase; int err = pci_device_map_range(pTrident->PciInfo, pTrident->IOAddress, mapsize, PCI_DEV_MAP_FLAG_WRITABLE, result); if (err) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map IO aperture. %s (%d)\n", strerror(err), err); } } #endif else { #ifndef XSERVER_LIBPCIACCESS pTrident->IOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO, pTrident->PciTag, pTrident->IOAddress, 0x1000); pTrident->IOBase += 0xF00; #else return FALSE; #endif } if (pTrident->IOBase == NULL) return FALSE; if (LINEAR()) { if (pTrident->FbMapSize != 0) { #ifndef XSERVER_LIBPCIACCESS pTrident->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, pTrident->PciTag, (unsigned long)pTrident->FbAddress, pTrident->FbMapSize); #else { void **result = (void **)&pTrident->FbBase; int err = pci_device_map_range(pTrident->PciInfo, pTrident->FbAddress, pTrident->FbMapSize, PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, result); if (err) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map VRAM aperture. %s (%d)\n", strerror(err), err); } } #endif if (pTrident->FbBase == NULL) return FALSE; } } else pTrident->FbBase = hwp->Base; return TRUE; } /* * Unmap the framebuffer and MMIO memory. */ static Bool TRIDENTUnmapMem(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int mapsize = 0x10000; if (Is3Dchip) mapsize = 0x20000; /* * Unmap IO registers to virtual address space */ #ifdef XSERVER_LIBPCIACCESS pci_device_unmap_range(pTrident->PciInfo, (pointer)pTrident->IOBase, mapsize); #else if (IsPciCard && UseMMIO) { xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, mapsize); } else { pTrident->IOBase -= 0xF00; xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, 0x1000); } #endif pTrident->IOBase = NULL; if (LINEAR()) { if (pTrident->FbMapSize != 0) { #ifdef XSERVER_LIBPCIACCESS pci_device_unmap_range(pTrident->PciInfo, (pointer)pTrident->FbBase, pTrident->FbMapSize); #else xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->FbBase, pTrident->FbMapSize); #endif pTrident->FbBase = NULL; } } return TRUE; } /* * GetAccelPitchValues - * * This function returns a list of display width (pitch) values that can * be used in accelerated mode. */ static int * GetAccelPitchValues(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int *linePitches = NULL; int lines[4] = { 512, 1024, 2048, 4096 }; /* 9440AGi */ int i, n = 0; if (pTrident->Chipset >= BLADEXP) { lines[0] = 1024; lines[1] = 2048; lines[2] = 4096; lines[3] = 8192; } for (i = 0; i < 4; i++) { n++; linePitches = XNFrealloc(linePitches, n * sizeof(int)); linePitches[n - 1] = lines[i]; } /* Mark the end of the list */ if (n > 0) { linePitches = XNFrealloc(linePitches, (n + 1) * sizeof(int)); linePitches[n] = 0; } return linePitches; } static void TRIDENTProbeDDC(ScrnInfoPtr pScrn, int index) { vbeInfoPtr pVbe; if (xf86LoadSubModule(pScrn, "vbe")) { pVbe = VBEInit(NULL,index); ConfiguredMonitor = vbeDoEDID(pVbe, NULL); vbeFree(pVbe); } } static void TRIDENTProtect(ScrnInfoPtr pScrn, Bool on) { vgaHWProtect(pScrn, on); } static void TRIDENTBlankScreen(ScrnInfoPtr pScrn, Bool on) { vgaHWBlankScreen(pScrn, on); } /* Mandatory */ static Bool TRIDENTProbe(DriverPtr drv, int flags) { int i; GDevPtr *devSections; int *usedChips = NULL; int numDevSections; int numUsed; Bool foundScreen = FALSE; if ((numDevSections = xf86MatchDevice(TRIDENT_DRIVER_NAME, &devSections)) <= 0) { /* * There's no matching device section in the config file, so quit * now. */ return FALSE; } /* * While we're VGA-dependent, can really only have one such instance, but * we'll ignore that. */ /* * 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. */ #ifndef XSERVER_LIBPCIACCESS if (xf86GetPciVideoInfo()== NULL) { return FALSE; } #endif { numUsed = xf86MatchPciInstances(TRIDENT_NAME, PCI_VENDOR_TRIDENT, TRIDENTChipsets, TRIDENTPciChipsets, devSections, numDevSections, drv, &usedChips); if (numUsed > 0) { if (flags & PROBE_DETECT) foundScreen = TRUE; else for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn = NULL; if ((pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i], TRIDENTPciChipsets, NULL, NULL, NULL, NULL, NULL))) { /* Fill in what we can of the ScrnInfoRec */ pScrn->driverVersion = TRIDENT_VERSION; pScrn->driverName = TRIDENT_DRIVER_NAME; pScrn->name = TRIDENT_NAME; pScrn->Probe = TRIDENTProbe; pScrn->PreInit = TRIDENTPreInit; pScrn->ScreenInit = TRIDENTScreenInit; pScrn->SwitchMode = TRIDENTSwitchMode; pScrn->AdjustFrame = TRIDENTAdjustFrame; pScrn->EnterVT = TRIDENTEnterVT; pScrn->LeaveVT = TRIDENTLeaveVT; pScrn->FreeScreen = TRIDENTFreeScreen; pScrn->ValidMode = TRIDENTValidMode; foundScreen = TRUE; } } free(usedChips); } } free(devSections); return foundScreen; } /* Mandatory */ static Bool TRIDENTPreInit(ScrnInfoPtr pScrn, int flags) { TRIDENTPtr pTrident; vgaHWPtr hwp; MessageType from; CARD8 videoram, videorammask; const char *ramtype = NULL, *chipset = NULL; Bool Support24bpp; int vgaIOBase; float mclk; double real; int i, NoClocks = 16; CARD8 revision; ClockRangePtr clockRanges; Bool ddcLoaded = FALSE; xf86MonPtr pMon = NULL; const char *s; Bool tmp_bool; /* Allocate the TRIDENTRec driverPrivate */ if (!TRIDENTGetRec(pScrn)) { return FALSE; } pTrident = TRIDENTPTR(pScrn); pTrident->pScrn = pScrn; if (pScrn->numEntities > 1) return FALSE; /* This is the general case */ for (i = 0; inumEntities; i++) { pTrident->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); #ifndef XSERVER_LIBPCIACCESS if (pTrident->pEnt->resources) return FALSE; #endif pTrident->Chipset = pTrident->pEnt->chipset; pScrn->chipset = (char *)xf86TokenToString(TRIDENTChipsets, pTrident->pEnt->chipset); /* This driver can handle ISA and PCI buses */ if (pTrident->pEnt->location.type == BUS_PCI) { pTrident->PciInfo = xf86GetPciInfoForEntity(pTrident->pEnt->index); #ifndef XSERVER_LIBPCIACCESS pTrident->PciTag = PCI_DEV_TAG(pTrident->PciInfo); #endif pTrident->Linear = TRUE; } else { pTrident->Linear = FALSE; } } if (flags & PROBE_DETECT) { TRIDENTProbeDDC(pScrn, pTrident->pEnt->index); return TRUE; } /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; /* * The first thing we should figure out is the depth, bpp, etc. * Our preference for depth 24 is 24bpp, so tell it that too. */ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | SupportConvert32to24 /*| PreferConvert32to24*/)) { return FALSE; } else { /* Check that the returned depth is one we support */ switch (pScrn->depth) { case 8: if (pScrn->bitsPerPixel != pScrn->depth) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", pScrn->depth, pScrn->bitsPerPixel); return FALSE; } break; case 15: case 16: if (pScrn->bitsPerPixel != 16) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", pScrn->depth, pScrn->bitsPerPixel); return FALSE; } break; case 24: if ((pScrn->bitsPerPixel != 24) && (pScrn->bitsPerPixel != 32)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", pScrn->depth, pScrn->bitsPerPixel); return FALSE; } /* OK */ break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by this driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); /* Get the depth24 pixmap format */ if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); /* The vgahw module should be loaded here when needed */ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; /* * Allocate a vgaHWRec */ if (!vgaHWGetHWRec(pScrn)) return FALSE; hwp = VGAHWPTR(pScrn); vgaHWSetStdFuncs(hwp); vgaHWGetIOBase(hwp); vgaIOBase = hwp->IOBase; pTrident->PIOBase = 0; /* was hwp->PIOOffset */ #ifndef XSERVER_LIBPCIACCESS xf86SetOperatingState(resVga, pTrident->pEnt->index, ResUnusedOpr); #endif /* The ramdac module should be loaded here when needed */ if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE; /* * 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)) { return FALSE; } else { /* XXX check that weight returned is supported */ ; } } if (!xf86SetDefaultVisual(pScrn, -1)) { return FALSE; } else { /* We don't currently support DirectColor at > 8bpp */ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" " (%s) is not supported at depth %d\n", xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); return FALSE; } } /* * The new cmap layer needs this to be initialised. */ { Gamma zeros = {0.0, 0.0, 0.0}; if (!xf86SetGamma(pScrn, zeros)) { return FALSE; } } /* Collect all of the relevant option flags (fill in pScrn->options) */ xf86CollectOptions(pScrn, NULL); /* Process the options */ if (!(pTrident->Options = malloc(sizeof(TRIDENTOptions)))) return FALSE; memcpy(pTrident->Options, TRIDENTOptions, sizeof(TRIDENTOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTrident->Options); /* Set the bits per RGB for 8bpp mode */ if (pScrn->depth == 8) { /* XXX This is here just to test options. */ /* Default to 8 */ pScrn->rgbBits = 6; #if 0 if (xf86GetOptValInteger(pTrident->Options, OPTION_RGB_BITS, &pScrn->rgbBits)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", pScrn->rgbBits); } #endif } from = X_DEFAULT; pTrident->useEXA = FALSE; if ((s = (char *)xf86GetOptValString(pTrident->Options, OPTION_ACCELMETHOD))) { if (!xf86NameCmp(s, "EXA")) { pTrident->useEXA = TRUE; from = X_CONFIG; } } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n", pTrident->useEXA ? "EXA" : "none"); pTrident->HWCursor = TRUE; if (xf86ReturnOptValBool(pTrident->Options, OPTION_SW_CURSOR, FALSE)) { from = X_CONFIG; pTrident->HWCursor = FALSE; } if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOACCEL, FALSE)) { pTrident->NoAccel = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_PCI_RETRY, FALSE)) { pTrident->UsePCIRetry = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); } pTrident->UsePCIBurst = TRUE; if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOPCIBURST, FALSE)) { pTrident->UsePCIBurst = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI Burst disabled\n"); } /* Display Size override moved to DDC section */ if(xf86GetOptValInteger(pTrident->Options, OPTION_VIDEO_KEY, &(pTrident->videoKey))) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pTrident->videoKey); } else { pTrident->videoKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOMMIO, FALSE)) { pTrident->NoMMIO = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO Disabled\n"); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_MMIO_ONLY, FALSE)) { if (pTrident->NoMMIO) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MMIO only cannot be set" " with NoMMIO\n"); else { pTrident->MMIOonly = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO only enabled\n"); } } pTrident->dspOverride = 0; if ((s = xf86GetOptValString(pTrident->Options, OPTION_DISPLAY))) { if(!xf86NameCmp(s, "CRT")) { pTrident->dspOverride = CRT_ACTIVE; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD off CRT on\n"); } else if (!xf86NameCmp(s, "LCD")) { pTrident->dspOverride = LCD_ACTIVE; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT off\n"); } else if (!xf86NameCmp(s, "Dual")) { pTrident->dspOverride = LCD_ACTIVE | CRT_ACTIVE; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT on\n"); } else xf86DrvMsg(pScrn->scrnIndex,X_ERROR, "%s is an unknown display option\n",s); } if ((s = xf86GetOptValString(pTrident->Options, OPTION_GB))) { int brightness = -1; double gamma = -1.0; Bool error = FALSE; int i; i = sscanf(s,"%lf %i",&gamma,&brightness); if (i != 2 || brightness == -1 || gamma == -1.0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid Gamma/Brightness argument: %s\n",s); error = TRUE; } else { if (brightness < 0 || brightness > 128) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "brightness out of range [0,128]: %i\n",brightness); error = TRUE; } if (gamma <= 0.0 || gamma > 10.0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "gamma out of range (0,10.0]: %f\n",gamma); error = TRUE; } } if (!error) { pTrident->GammaBrightnessOn = TRUE; pTrident->gamma = gamma; pTrident->brightness = brightness; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Gamma: %f Brightness: %i\n", gamma,brightness); } } /* The following is a temporary hack */ pTrident->FPDelay = 7; /* invalid value */ if (xf86GetOptValInteger(pTrident->Options, OPTION_FP_DELAY, &pTrident->FPDelay)) { if (pTrident->FPDelay < -2 || pTrident->FPDelay > 5) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FPDelay %i out if range " "(-2 < FPDelay < 5)\n",pTrident->FPDelay); pTrident->FPDelay = 7; } else xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP Delay set to %i\n", pTrident->FPDelay); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_SHADOW, FALSE)) { pTrident->CyberShadow = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Shadow enabled\n"); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_STRETCH, FALSE)) { pTrident->CyberStretch = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Stretch enabled\n"); } pTrident->MUXThreshold = 90000; /* 90MHz */ if (xf86GetOptValInteger(pTrident->Options, OPTION_MUX_THRESHOLD, &pTrident->MUXThreshold)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MUX Threshold set to %d\n", pTrident->MUXThreshold); } pTrident->OverrideHsync = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC, &pTrident->OverrideHsync)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n", pTrident->OverrideHsync); } pTrident->OverrideVsync = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC, &pTrident->OverrideVsync)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n", pTrident->OverrideVsync); } pTrident->OverrideHsync = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC, &pTrident->OverrideHsync)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n", pTrident->OverrideHsync); } pTrident->OverrideVsync = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC, &pTrident->OverrideVsync)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n", pTrident->OverrideVsync); } pTrident->OverrideRskew = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_RSKEW, &pTrident->OverrideRskew)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Rskew set to %d\n", pTrident->OverrideRskew); } pTrident->OverrideBskew = 0; if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_BSKEW, &pTrident->OverrideBskew)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Bskew set to %d\n", pTrident->OverrideBskew); } if (xf86ReturnOptValBool(pTrident->Options, OPTION_SHADOW_FB, FALSE)) { if (!LINEAR()) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option SHADOW_FB" " in non-Linear Mode\n"); else { pTrident->ShadowFB = TRUE; pTrident->NoAccel = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\" - acceleration disabled\n"); } } pTrident->Rotate = 0; if ((s = xf86GetOptValString(pTrident->Options, OPTION_ROTATE))) { if (!LINEAR()) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option ROTATE " "in non-Linear Mode\n"); else { if(!xf86NameCmp(s, "CW")) { /* accel is disabled below for shadowFB */ pTrident->ShadowFB = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; pTrident->Rotate = 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen clockwise - acceleration disabled\n"); } else if(!xf86NameCmp(s, "CCW")) { pTrident->ShadowFB = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; pTrident->Rotate = -1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" "counter clockwise - acceleration disabled\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" "value for Option \"Rotate\"\n", s); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or \"CCW\"\n"); } } } pTrident->TVChipset = 0; if ((s = xf86GetOptValString(pTrident->Options, OPTION_TV_CHIPSET))) { if(!xf86NameCmp(s, "VT1621")) { pTrident->TVChipset = 1; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using VIA VT1621 TV chip\n"); } else if (!xf86NameCmp(s, "CH7005")) { pTrident->TVChipset = 2; xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using Chrontel CH7005 TV chip\n"); } else xf86DrvMsg(pScrn->scrnIndex,X_ERROR, "%s is an unknown TV chipset option\n",s); } /* Default : NTSC */ pTrident->TVSignalMode=0; if (xf86GetOptValInteger(pTrident->Options, OPTION_TV_SIGNALMODE, &pTrident->TVSignalMode)) { ErrorF("TV SignalMode set to %d\n",pTrident->TVSignalMode); } /* FIXME ACCELERATION */ if (!UseMMIO) pTrident->NoAccel = TRUE; if (LINEAR()) { if (pTrident->pEnt->device->MemBase != 0) { /* * XXX Should check that the config file value matches one of the * PCI base address values. */ pTrident->FbAddress = pTrident->pEnt->device->MemBase; from = X_CONFIG; } else { if (IsPciCard) pTrident->FbAddress = PCI_REGION_BASE(pTrident->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; else pTrident->FbAddress = 0xA0000; } xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", (unsigned long)pTrident->FbAddress); } if (UseMMIO) { if (pTrident->pEnt->device->IOBase != 0) { /* * XXX Should check that the config file value matches one of the * PCI base address values. */ pTrident->IOAddress = pTrident->pEnt->device->IOBase; from = X_CONFIG; } else { if (IsPciCard) pTrident->IOAddress = PCI_REGION_BASE(pTrident->PciInfo, 1, REGION_MEM) & 0xFFFFC000; else /* FIXME - Multihead UNAWARE */ pTrident->IOAddress = 0xBF000; } xf86DrvMsg(pScrn->scrnIndex,X_PROBED,"IO registers at 0x%lX\n", (unsigned long)pTrident->IOAddress); } #ifndef XSERVER_LIBPCIACCESS /* Register the PCI-assigned resources. */ if (xf86RegisterResources(pTrident->pEnt->index, NULL, ResExclusive)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86RegisterResources() found resource conflicts\n"); return FALSE; } #endif /* Initialize VBE if possible * Don't move this past MMIO enable!! * PIO access will be blocked * when MMIO is turned on! */ if (xf86LoadSubModule(pScrn, "vbe")) { vbeInfoPtr pVbe; pVbe = VBEInit(NULL,pTrident->pEnt->index); pMon = vbeDoEDID(pVbe, NULL); #ifdef VBE_INFO { VbeInfoBlock* vbeInfoBlockPtr; if ((vbeInfoBlockPtr = VBEGetVBEInfo(pVbe))) { pTrident->vbeModes = VBEBuildVbeModeList(pVbe,vbeInfoBlockPtr); VBEFreeVBEInfo(vbeInfoBlockPtr); } } #endif vbeFree(pVbe); if (pMon) { if (!xf86LoadSubModule(pScrn, "ddc")) { TRIDENTFreeRec(pScrn); return FALSE; } else { xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon)); ddcLoaded = TRUE; } } } if (xf86GetOptValBool(pTrident->Options, OPTION_1400_DISPLAY, &tmp_bool)) { if (tmp_bool) pTrident->displaySize = 1400; } else pTrident->displaySize = TRIDENTLcdDisplaySize(pMon); if (IsPciCard && UseMMIO) { if (!TRIDENTMapMem(pScrn)) return FALSE; TRIDENTEnableMMIO(pScrn); } OUTB(0x3C4, RevisionID); revision = INB(0x3C5); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Revision is %d\n",revision); pScrn->progClock = TRUE; pTrident->EngineOperation = 0x00; pTrident->IsCyber = FALSE; pTrident->HasSGRAM = FALSE; pTrident->NewClockCode = FALSE; pTrident->MUX = FALSE; Support24bpp = FALSE; OUTB(vgaIOBase + 4, InterfaceSel); switch (pTrident->Chipset) { case TVGA9000: case TVGA9000i: pScrn->progClock = FALSE; NoClocks = 16; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA9000/9000i"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TVGA9100B: pScrn->progClock = FALSE; NoClocks = 8; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA9100B"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TVGA8900B: pScrn->progClock = FALSE; NoClocks = 8; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA8900B"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TVGA8900C: pScrn->progClock = FALSE; NoClocks = 16; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA8900C"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TVGA8900D: pScrn->progClock = FALSE; NoClocks = 16; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA8900D"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TVGA9200CXr: pScrn->progClock = FALSE; NoClocks = 16; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA9200CXr"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TGUI9400CXi: pScrn->progClock = FALSE; NoClocks = 16; pTrident->NoMMIO = TRUE; pTrident->NoAccel = TRUE; pTrident->HWCursor = FALSE; chipset = "TVGA9200CXr"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case TGUI9440AGi: pTrident->ddc1Read = Tridentddc1Read; pTrident->HWCursor = FALSE; chipset = "TGUI9440AGi"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ pTrident->frequency = NTSC; break; case CYBER9320: pTrident->ddc1Read = Tridentddc1Read; chipset = "Cyber9320"; ramtype = "Standard DRAM"; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ break; /* Trident didn't update the PCI ID's and so we have to determine * which chips are right ! Then override pTrident->Chipset to * correct values */ case TGUI9660: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) ramtype = "Standard DRAM"; switch (revision) { case 0x00: chipset = "TGUI9660"; pTrident->Chipset = TGUI9660; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ break; case 0x01: chipset = "TGUI9680"; pTrident->Chipset = TGUI9680; if (pTrident->UsePCIRetry) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); pTrident->UsePCIRetry = FALSE; /* Not Supported */ break; case 0x10: chipset = "ProVidia 9682"; Support24bpp = TRUE; pTrident->Chipset = PROVIDIA9682; break; case 0x21: chipset = "ProVidia 9685"; Support24bpp = TRUE; pTrident->NewClockCode = TRUE; pTrident->Chipset = PROVIDIA9685; break; case 0x22: case 0x23: chipset = "Cyber 9397"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9397; pTrident->IsCyber = TRUE; break; case 0x2a: chipset = "Cyber 9397/DVD"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9397DVD; pTrident->IsCyber = TRUE; break; case 0x30: case 0x33: case 0x34: case 0x35: case 0xB3: chipset = "Cyber 9385"; pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9385; pTrident->IsCyber = TRUE; break; case 0x38: case 0x3A: chipset = "Cyber 9385-1"; pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9385; pTrident->IsCyber = TRUE; break; case 0x40: case 0x41: case 0x42: case 0x43: chipset = "Cyber 9382"; pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9382; pTrident->IsCyber = TRUE; break; case 0x4A: chipset = "Cyber 9388"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->NewClockCode = TRUE; pTrident->Chipset = CYBER9388; pTrident->IsCyber = TRUE; break; default: chipset = "Unknown"; pTrident->Chipset = TGUI9660; break; } break; case CYBER9388: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "Cyber 9388"; pTrident->NewClockCode = TRUE; break; case CYBER9397: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "Cyber 9397"; pTrident->NewClockCode = TRUE; break; case CYBER9397DVD: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "Cyber 9397/DVD"; pTrident->NewClockCode = TRUE; break; case CYBER9520: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "Cyber 9520"; pTrident->NewClockCode = TRUE; break; case CYBER9525DVD: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "Cyber 9525/DVD"; pTrident->NewClockCode = TRUE; break; case CYBERBLADEE4: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade e4/128"; pTrident->NewClockCode = TRUE; break; case IMAGE975: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } Support24bpp = TRUE; chipset = "3DImage975"; pTrident->NewClockCode = TRUE; break; case IMAGE985: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) ramtype = "EDO Ram"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } Support24bpp = TRUE; chipset = "3DImage985"; pTrident->NewClockCode = TRUE; break; case BLADE3D: pTrident->ddc1Read = Tridentddc1Read; if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) ramtype = "SDRAM"; if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { pTrident->HasSGRAM = TRUE; ramtype = "SGRAM"; } Support24bpp = TRUE; chipset = "Blade3D"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; pTrident->UsePCIRetry = TRUE; /* To avoid lockups */ break; case CYBERBLADEI7: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; /* pTrident->IsCyber = TRUE; VIA MVP4 integrated Desktop version */ Support24bpp = TRUE; chipset = "CyberBlade/i7/VIA MVP4"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEI7D: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade/DSTN/i7"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEI1: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade/i1"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEI1D: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade/DSTN/i1"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEAI1: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade/Ai1"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEAI1D: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SDRAM"; pTrident->IsCyber = TRUE; Support24bpp = TRUE; chipset = "CyberBlade/DSTN/Ai1"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case BLADEXP: /* 0x9910 */ pTrident->ddc1Read = Tridentddc1Read; ramtype = "SGRAM"; pTrident->HasSGRAM = TRUE; Support24bpp = TRUE; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; OUTB(0x3C4, 0x5D); if (PCI_SUB_VENDOR_ID(pTrident->PciInfo) != 0x1023) { chipset = "CyberBladeXP"; pTrident->IsCyber = TRUE; } else if (!(INB(0x3C5) & 0x01)) { chipset = "BladeXP"; } else { CARD8 mem1, mem2; OUTB(vgaIOBase + 0x04, SPR); mem1 = INB(vgaIOBase + 5); OUTB(vgaIOBase + 0x04, 0xC1); mem2 = INB(vgaIOBase + 5); if ((mem1 & 0x0e) && (mem2 == 0x11)) { chipset = "BladeT64"; } else { chipset = "BladeT16"; } } break; case CYBERBLADEXPAI1: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SGRAM"; pTrident->HasSGRAM = TRUE; pTrident->IsCyber = TRUE; pTrident->shadowNew = TRUE; Support24bpp = TRUE; chipset = "CyberBladeXPAi1"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case CYBERBLADEXP4: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SGRAM"; pTrident->HasSGRAM = TRUE; pTrident->IsCyber = TRUE; pTrident->shadowNew = TRUE; Support24bpp = TRUE; chipset = "CyberBladeXP4"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; case XP5: pTrident->ddc1Read = Tridentddc1Read; ramtype = "SGRAM"; pTrident->HasSGRAM = TRUE; pTrident->IsCyber = TRUE; pTrident->shadowNew = TRUE; Support24bpp = TRUE; chipset = "XP5"; pTrident->NewClockCode = TRUE; pTrident->frequency = NTSC; break; } if (!pScrn->progClock) { pScrn->numClocks = NoClocks; xf86GetClocks(pScrn, NoClocks, TRIDENTClockSelect, TRIDENTProtect, TRIDENTBlankScreen, vgaIOBase + 0x0A, 0x08, 1, 28322); from = X_PROBED; xf86ShowClocks(pScrn, from); } if (!chipset) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No support for \"%s\"\n", pScrn->chipset); if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } return FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Found %s chip\n", chipset); if (ramtype) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RAM type is %s\n", ramtype); if (pScrn->bitsPerPixel == 24 && !Support24bpp) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No support for 24bpp on this chipset, use -pixmap32.\n"); if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } return FALSE; } /* HW bpp matches reported bpp */ pTrident->HwBpp = pScrn->bitsPerPixel; /* Due to bugs in the chip, turn it off */ if (pTrident->Chipset >= CYBERBLADEI7 && pTrident->Chipset <= CYBERBLADEAI1D) pTrident->HWCursor = FALSE; from = X_PROBED; if (pTrident->pEnt->device->videoRam != 0) { pScrn->videoRam = pTrident->pEnt->device->videoRam; from = X_CONFIG; } else { if (pTrident->Chipset == XP5) { OUTB(vgaIOBase + 4, 0x60); videoram = INB(vgaIOBase + 5); switch (videoram & 0x7) { case 0x00: pScrn->videoRam = 65536 /* 131072 */; break; case 0x01: pScrn->videoRam = 65536; break; case 0x02: pScrn->videoRam = 32768; break; case 0x03: pScrn->videoRam = 16384; break; case 0x04: pScrn->videoRam = 8192; break; } } else if (pTrident->Chipset == CYBER9525DVD) { pScrn->videoRam = 2560; } else { OUTB(vgaIOBase + 4, SPR); videoram = INB(vgaIOBase + 5); if (pTrident->Chipset < TGUI9440AGi) videorammask = 0x07; else videorammask = 0x0F; switch (videoram & videorammask) { case 0x01: pScrn->videoRam = 512; break; case 0x02: /* XP */ pScrn->videoRam = 6144; break; case 0x03: pScrn->videoRam = 1024; break; case 0x04: pScrn->videoRam = 8192; break; case 0x06: /* XP */ pScrn->videoRam = 10240; break; case 0x07: pScrn->videoRam = 2048; break; case 0x08: /* XP */ pScrn->videoRam = 12288; break; case 0x0A: /* XP */ pScrn->videoRam = 14336; break; case 0x0C: /* XP */ pScrn->videoRam = 16384; break; case 0x0E: /* XP */ OUTB(vgaIOBase + 4, 0xC1); switch (INB(vgaIOBase + 5) & 0x11) { case 0x00: pScrn->videoRam = 20480; break; case 0x01: pScrn->videoRam = 24576; break; case 0x10: pScrn->videoRam = 28672; break; case 0x11: pScrn->videoRam = 32768; break; } break; case 0x0F: pScrn->videoRam = 4096; break; default: pScrn->videoRam = 1024; xf86DrvMsg(pScrn->scrnIndex, from, "Unable to determine VideoRam, defaulting to 1MB\n"); break; } } } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", pTrident->HWCursor ? "HW" : "SW"); xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", pScrn->videoRam); if (pTrident->IsCyber) { unsigned char mod, dsp, dsp1; pTrident->lcdMode = 0xff; OUTB(0x3CE,0x42); dsp = INB(0x3CF); OUTB(0x3CE,0x43); dsp1 = INB(0x3CF); OUTB(0x3CE,0x52); mod = INB(0x3CF); /* * Only allow display size override if 1280x1024 is detected * Currently 1400x1050 is supported - which is detected as * 1280x1024 */ if (pTrident->displaySize) { if (((mod >> 4) & 3) == 0) { for (i = 0; LCD[i].mode != 0xff; i++) { if (pTrident->displaySize == LCD[i].display_x) pTrident->lcdMode = LCD[i].mode; } xf86DrvMsg(pScrn->scrnIndex, X_INFO,"%s Panel %ix%i found\n", (dsp & 0x80) ? "TFT" : ((dsp1 & 0x20) ? "DSTN" : "STN"), LCD[i].display_x,LCD[i].display_y); } else { xf86DrvMsg(pScrn->scrnIndex,X_WARNING, "Display size override only for 1280x1024\n"); pTrident->displaySize = 0; } } if (!pTrident->displaySize) { for (i = 0; LCD[i].mode != 0xff; i++) { if (LCD[i].mode == ((mod >> 4) & 3)) { pTrident->lcdMode = i; xf86DrvMsg(pScrn->scrnIndex, X_PROBED,"%s Panel %ix%i found\n", (dsp & 0x80) ? "TFT" : ((dsp1 & 0x20) ? "DSTN" : "STN"), LCD[i].display_x,LCD[i].display_y); } } } if (pTrident->dspOverride) { if (pTrident->dspOverride & LCD_ACTIVE) pTrident->lcdActive = TRUE; else pTrident->lcdActive = FALSE; } else { OUTB(0x3CE, FPConfig); pTrident->lcdActive = (INB(0x3CF) & 0x10); } } pTrident->MCLK = 0; mclk = CalculateMCLK(pScrn); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory Clock is %3.2f MHz\n", mclk); if (xf86GetOptValFreq(pTrident->Options, OPTION_SETMCLK, OPTUNITS_MHZ, &real)) { pTrident->MCLK = (int)(real * 1000.0); xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting new Memory Clock to %3.2f MHz\n", (float)(pTrident->MCLK / 1000)); } /* Set the min pixel clock */ pTrident->MinClock = 12000; /* XXX Guess, need to check this */ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", pTrident->MinClock / 1000); /* * If the user has specified ramdac speed in the XF86Config * file, we respect that setting. */ if (pTrident->pEnt->device->dacSpeeds[0]) { int speed = 0; switch (pScrn->bitsPerPixel) { case 8: speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP8]; break; case 16: speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP16]; break; case 24: speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP24]; break; case 32: speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP32]; break; } if (speed == 0) pTrident->MaxClock = pTrident->pEnt->device->dacSpeeds[0]; else pTrident->MaxClock = speed; from = X_CONFIG; } else { switch (pScrn->bitsPerPixel) { case 16: pTrident->MaxClock = ClockLimit16bpp[pTrident->Chipset]; break; case 24: pTrident->MaxClock = ClockLimit24bpp[pTrident->Chipset]; break; case 32: pTrident->MaxClock = ClockLimit32bpp[pTrident->Chipset]; break; default: pTrident->MaxClock = ClockLimit[pTrident->Chipset]; break; } } xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", pTrident->MaxClock / 1000); /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. */ clockRanges = XNFcallocarray(sizeof(ClockRange), 1); clockRanges->next = NULL; if (!pScrn->progClock) { if (pScrn->videoRam < 1024) clockRanges->ClockMulFactor = 2; if (pScrn->bitsPerPixel == 16) clockRanges->ClockMulFactor = 2; } clockRanges->minClock = pTrident->MinClock; clockRanges->maxClock = pTrident->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 TRIDENTValidMode() already takes * care of this, we don't worry about setting them here. */ if (pScrn->bitsPerPixel == 24) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Disabling Engine due to 24bpp.\n"); pTrident->NoAccel = TRUE; } /* Select valid modes from those available */ if (pTrident->NoAccel || Is3Dchip) { /* * XXX Assuming min pitch 256, max 4096 * XXX Assuming min height 128, max 4096 */ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, 256, 4096, pScrn->bitsPerPixel, 128, 4096, pScrn->display->virtualX, pScrn->display->virtualY, pTrident->FbMapSize, LOOKUP_BEST_REFRESH); } else { /* * XXX Assuming min height 128, max 2048 */ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, GetAccelPitchValues(pScrn), 0, 0, pScrn->bitsPerPixel, 128, 2048, pScrn->display->virtualX, pScrn->display->virtualY, pTrident->FbMapSize, LOOKUP_BEST_REFRESH); } if (i == -1) { if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } /* Prune the modes marked as invalid */ xf86PruneDriverModes(pScrn); if (i == 0 || pScrn->modes == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); /* Set the current mode to the first in the list */ pScrn->currentMode = pScrn->modes; /* Print the list of modes being used */ xf86PrintModes(pScrn); /* Set display resolution */ xf86SetDpi(pScrn, 0, 0); /* Load bpp-specific modules */ switch (pScrn->bitsPerPixel) { case 8: pTrident->EngineOperation |= 0x00; break; case 16: pTrident->EngineOperation |= 0x01; break; case 24: pTrident->EngineOperation |= 0x03; break; case 32: pTrident->EngineOperation |= 0x02; break; } if (xf86LoadSubModule(pScrn, "fb") == NULL) { if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } if (!xf86LoadSubModule(pScrn, "i2c")) { if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } /* Load EXA if needed */ if (!pTrident->NoAccel) { if (!pTrident->useEXA) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n"); pTrident->NoAccel = 1; pTrident->ShadowFB = 1; } if (pTrident->useEXA) { XF86ModReqInfo req; int errmaj, errmin; memset(&req, 0, sizeof(req)); req.majorversion = 2; if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, &errmaj, &errmin)) { LoaderErrorMsg(NULL, "exa", errmaj, errmin); if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } } switch (pScrn->displayWidth * pScrn->bitsPerPixel / 8) { case 512: case 8192: pTrident->EngineOperation |= 0x00; break; case 1024: pTrident->EngineOperation |= 0x04; break; case 2048: pTrident->EngineOperation |= 0x08; break; case 4096: pTrident->EngineOperation |= 0x0C; break; } } /* Load shadow if needed */ if (pTrident->ShadowFB) { if (!xf86LoadSubModule(pScrn, "shadow")) { TRIDENTFreeRec(pScrn); return FALSE; } } /* Load DDC if needed */ /* This gives us DDC1 - we should be able to get DDC2B using i2c */ if (! ddcLoaded) if (!xf86LoadSubModule(pScrn, "ddc")) { if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } TRIDENTFreeRec(pScrn); return FALSE; } if (IsPciCard && UseMMIO) { TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } #ifndef XSERVER_LIBPCIACCESS pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; if (pTrident->IsCyber && pTrident->MMIOonly) pScrn->racIoFlags = 0; else pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; #endif pTrident->FbMapSize = pScrn->videoRam * 1024; return TRUE; } /* * 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 TRIDENTCloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); vgaHWPtr hwp = VGAHWPTR(pScrn); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); if (pScrn->vtSema) { if (!pTrident->NoAccel && pTrident->useEXA) pTrident->EXADriverPtr->WaitMarker(pScreen, 0); TRIDENTRestore(pScrn); vgaHWLock(hwp); if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); TRIDENTUnmapMem(pScrn); } if (pTrident->EXADriverPtr) { exaDriverFini(pScreen); free(pTrident->EXADriverPtr); pTrident->EXADriverPtr = NULL; } if (pTrident->CursorInfoRec) xf86DestroyCursorInfoRec(pTrident->CursorInfoRec); if (pTrident->ShadowPtr) { shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); free(pTrident->ShadowPtr); pScreen->CreateScreenResources = pTrident->CreateScreenResources; } if (pTrident->DGAModes) free(pTrident->DGAModes); pScrn->vtSema = FALSE; if(pTrident->BlockHandler) pScreen->BlockHandler = pTrident->BlockHandler; if (pTrident->pVbe) vbeFree(pTrident->pVbe); else xf86FreeInt10(pTrident->Int10); pScreen->CloseScreen = pTrident->CloseScreen; return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); } /* Do screen blanking */ /* Mandatory */ static Bool TRIDENTSaveScreen(ScreenPtr pScreen, int mode) { return vgaHWSaveScreen(pScreen, mode); } static Bool TRIDENTCreateScreenResources(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); Bool ret; pScreen->CreateScreenResources = pTrident->CreateScreenResources; ret = pScreen->CreateScreenResources(pScreen); pTrident->CreateScreenResources = pScreen->CreateScreenResources; pScreen->CreateScreenResources = TRIDENTCreateScreenResources; if (ret) ret = shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), TRIDENTShadowUpdate, NULL, 0, 0); return ret; } /* Mandatory */ /* This gets called at the start of each server generation */ static Bool TRIDENTScreenInit(SCREEN_INIT_ARGS_DECL) { /* The vgaHW references will disappear one day */ ScrnInfoPtr pScrn; vgaHWPtr hwp; TRIDENTPtr pTrident; int ret; VisualPtr visual; unsigned char *FBStart; int width, height, displayWidth; /* * First get the ScrnInfoRec */ pScrn = xf86ScreenToScrn(pScreen); pTrident = TRIDENTPTR(pScrn); if (IsPrimaryCard) { if (!vgaHWMapMem(pScrn)) return FALSE; } /* Map the TRIDENT memory and MMIO areas */ if (!TRIDENTMapMem(pScrn)) return FALSE; #ifdef VBE_INFO if (pTrident->vbeModes) { pTrident->pVbe = VBEInit(NULL,pTrident->pEnt->index); pTrident->Int10 = pTrident->pVbe->pInt10; } else #endif { if (xf86LoadSubModule(pScrn, "int10")) { xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Initializing int10\n"); pTrident->Int10 = xf86InitInt10(pTrident->pEnt->index); } } hwp = VGAHWPTR(pScrn); if (IsPciCard && UseMMIO) { TRIDENTEnableMMIO(pScrn); /* Initialize the MMIO vgahw functions */ vgaHWSetMmioFuncs(hwp, pTrident->IOBase, 0); } /* Save the current state */ TRIDENTSave(pScrn); tridentSetModeBIOS(pScrn,pScrn->currentMode); /* Initialise the first mode */ if (!TRIDENTModeInit(pScrn, pScrn->currentMode)) return FALSE; /* Darken the screen for aesthetic reasons and set the viewport */ TRIDENTSaveScreen(pScreen, SCREEN_SAVER_ON); TRIDENTAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); /* * 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 fb uses * are not appropriate. In this driver, we fixup the visuals after. */ /* * Reset visual list. */ miClearVisualTypes(); /* Setup the visuals we support. */ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) { if (pTrident->pVbe) vbeFree(pTrident->pVbe); else xf86FreeInt10(pTrident->Int10); return FALSE; } miSetPixmapDepths (); /* FIXME - we don't do shadowfb for < 4 */ displayWidth = pScrn->displayWidth; if (pTrident->Rotate) { height = pScrn->virtualX; width = pScrn->virtualY; } else { width = pScrn->virtualX; height = pScrn->virtualY; } if(pTrident->ShadowFB) { pTrident->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); pTrident->ShadowPtr = malloc(pTrident->ShadowPitch * height); displayWidth = pTrident->ShadowPitch / (pScrn->bitsPerPixel >> 3); FBStart = pTrident->ShadowPtr; } else { pTrident->ShadowFB = FALSE; pTrident->ShadowPtr = NULL; FBStart = pTrident->FbBase; } /* * Call the framebuffer layer's ScreenInit function, and fill in other * pScreen fields. */ switch (pScrn->bitsPerPixel) { case 8: case 16: case 24: case 32: ret = fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi, pScrn->yDpi, displayWidth, pScrn->bitsPerPixel); break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: invalid bpp (%d) in TRIDENTScrnInit\n", pScrn->bitsPerPixel); ret = FALSE; break; } if (!ret) { if (pTrident->pVbe) vbeFree(pTrident->pVbe); else xf86FreeInt10(pTrident->Int10); 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; } } } /* must be after RGB ordering fixed */ fbPictureInit (pScreen, 0, 0); xf86SetBlackWhitePixels(pScreen); pTrident->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = TRIDENTBlockHandler; if (!pTrident->ShadowFB) TRIDENTDGAInit(pScreen); { BoxRec AvailFBArea; AvailFBArea.x1 = 0; AvailFBArea.y1 = 0; AvailFBArea.x2 = pScrn->displayWidth; AvailFBArea.y2 = pTrident->FbMapSize / (pScrn->displayWidth * pScrn->bitsPerPixel / 8); if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047; if (xf86InitFBManager(pScreen, &AvailFBArea)) { int cpp = pScrn->bitsPerPixel / 8; int area = AvailFBArea.y2 * pScrn->displayWidth; int areaoffset = area * cpp; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %i scanlines of offscreen memory for area's \n", AvailFBArea.y2 - pScrn->virtualY); if (xf86InitFBManagerLinear(pScreen, area, ((pTrident->FbMapSize/cpp) - area))) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %ld bytes of offscreen memory for linear (offset=0x%x)\n", (pTrident->FbMapSize - areaoffset), areaoffset); } } } if (Is3Dchip) { if ((pTrident->Chipset == CYBERBLADEI7) || (pTrident->Chipset == CYBERBLADEI7D) || (pTrident->Chipset == CYBERBLADEI1) || (pTrident->Chipset == CYBERBLADEI1D) || (pTrident->Chipset == CYBERBLADEAI1) || (pTrident->Chipset == CYBERBLADEAI1D) || (pTrident->Chipset == CYBERBLADEE4) || (pTrident->Chipset == BLADE3D)) { if (pTrident->useEXA) BladeExaInit(pScreen); } else if ((pTrident->Chipset == CYBERBLADEXP4) || (pTrident->Chipset == XP5)) { if (pTrident->useEXA) XP4ExaInit(pScreen); } } xf86SetBackingStore(pScreen); /* Initialise cursor functions */ miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); if (pTrident->HWCursor) { xf86SetSilkenMouse(pScreen); TridentHWCursorInit(pScreen); } /* Initialise default colourmap */ if (!miCreateDefColormap(pScreen)) { if (pTrident->pVbe) vbeFree(pTrident->pVbe); else xf86FreeInt10(pTrident->Int10); return FALSE; } if(!xf86HandleColormaps(pScreen, 256, 6, TridentLoadPalette, TridentSetOverscan, CMAP_RELOAD_ON_MODE_SWITCH|CMAP_PALETTED_TRUECOLOR)) { if (pTrident->pVbe) vbeFree(pTrident->pVbe); else xf86FreeInt10(pTrident->Int10); return FALSE; } if(pTrident->ShadowFB) { if(pTrident->Rotate) { if (!pTrident->PointerMoved) { pTrident->PointerMoved = pScrn->PointerMoved; pScrn->PointerMoved = TRIDENTPointerMoved; } switch (pScrn->bitsPerPixel) { case 8: pTrident->RefreshArea = TRIDENTRefreshArea8; break; case 16: pTrident->RefreshArea = TRIDENTRefreshArea16; break; case 24: pTrident->RefreshArea = TRIDENTRefreshArea24; break; case 32: pTrident->RefreshArea = TRIDENTRefreshArea32; break; } } else { pTrident->RefreshArea = TRIDENTRefreshArea; } if (!shadowSetup(pScreen)) return FALSE; pTrident->CreateScreenResources = pScreen->CreateScreenResources; pScreen->CreateScreenResources = TRIDENTCreateScreenResources; } xf86DPMSInit(pScreen, (DPMSSetProcPtr)TRIDENTDisplayPowerManagementSet, 0); pScrn->memPhysBase = pTrident->FbAddress; pScrn->fbOffset = 0; if (pTrident->Chipset >= TGUI9660) TRIDENTInitVideo(pScreen); pTrident->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = TRIDENTCloseScreen; pScreen->SaveScreen = TRIDENTSaveScreen; /* Report any unused options (only for the first generation) */ if (serverGeneration == 1) { xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); } #if 0 TRIDENTI2CInit(pScreen); xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,pTrident->DDC)); #endif return TRUE; }