diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c | 293 |
1 files changed, 286 insertions, 7 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c b/xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c index 892b3737f..251574a01 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c @@ -21,7 +21,7 @@ * * Author: Alan Hourihane, alanh@fairlite.demon.co.uk */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c,v 1.18 2000/02/17 21:36:23 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c,v 1.23 2000/06/23 18:25:58 eich Exp $ */ #include "xf86.h" #include "xf86_OSproc.h" @@ -35,6 +35,109 @@ #include "trident.h" #include "trident_regs.h" +extern tridentLCD LCD[]; + +biosMode bios1[] = { + { 640, 480, 0x11 } +}; + +biosMode bios4[] = { + { 320, 200, 0xd }, + { 640, 200, 0xe }, + { 640, 350, 0x11 }, + { 640, 480, 0x12 }, + { 800, 600, 0x5b }, + { 1024, 768 , 0x5f }, + { 1280, 1024, 0x63 }, + { 1600, 1200, 0x65 } +}; + +biosMode bios8[] = { + { 320, 200, 0x13 }, + { 640, 400, 0x52 }, + { 640, 480, 0x5d }, + { 720, 480, 0x60 }, + { 1024, 768, 0x62 }, + { 1280, 1024, 0x64 }, + { 1600, 1200, 0x66 } +}; + +biosMode bios15[] = { + { 640, 400, 0x72 }, + { 640, 480, 0x74 }, + { 720, 480, 0x70 }, + { 800, 600, 0x76 }, + { 1024, 768, 0x78 } +}; + +biosMode bios16[] = { + { 640, 400, 0x73 }, + { 640, 480, 0x75 }, + { 720, 480, 0x71 }, + { 800, 600, 0x77 }, + { 1024, 768, 0x79 } +}; + +biosMode bios24[] = { + { 640, 400, 0x6b }, + { 640, 480, 0x6c }, + { 720, 480, 0x61 }, + { 800, 600, 0x6d }, + { 1024, 768, 0x6e } +}; + + +static int +findMode(int xres, int yres, int depth) +{ + int xres_s; + int i, size; + biosMode *mode; + + switch (depth) { + case 1: + size = sizeof(bios1) / sizeof(biosMode); + mode = bios1; + break; + case 4: + size = sizeof(bios4) / sizeof(biosMode); + mode = bios4; + break; + case 8: + size = sizeof(bios8) / sizeof(biosMode); + mode = bios8; + break; + case 15: + size = sizeof(bios15) / sizeof(biosMode); + mode = bios15; + break; + case 16: + size = sizeof(bios16) / sizeof(biosMode); + mode = bios16; + break; + case 24: + size = sizeof(bios24) / sizeof(biosMode); + mode = bios24; + break; + default: + return 0; + } + + for (i = 0; i < size; i++) { + if (xres <= mode[i].x_res) { + xres_s = mode[i].x_res; + for (; i < size; i++) { + if (mode[i].x_res != xres_s) + return mode[i-1].mode; + if (yres <= mode[i].y_res) + return mode[i].mode; + } + } + } + return mode[size - 1].mode; + +} + Bool TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { @@ -43,8 +146,18 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) int vgaIOBase; int offset = 0; int clock = mode->Clock; + CARD8 protect; + + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->ModeReg; vgaHWGetIOBase(VGAHWPTR(pScrn)); vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + + /* Unprotect */ + OUTB(0x3C4, 0x11); + protect = INB(0x3C4); + OUTB(0x3C5, 0x92); OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ @@ -60,6 +173,7 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) case CYBERBLADEI7: case CYBERBLADEI7D: case CYBERBLADEI1: + case CYBERBLADEI1D: case BLADE3D: OUTB(vgaIOBase + 4, RAMDACTiming); pReg->tridentRegs3x4[RAMDACTiming] |= 0x0F; @@ -101,6 +215,15 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) } if (pTrident->IsCyber) { + Bool LCDActive; + Bool ShadowModeActive; + int i; + + OUTB(0x3CE, CyberControl); + ShadowModeActive = ((INB(0x3CF) & 0x81) == 0x81); + OUTB(0x3CE, FPConfig); + LCDActive = (INB(0x3CF) & 0x10); + OUTB(0x3CE, CyberEnhance); pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF) & 0x8F; if (mode->CrtcVDisplay > 768) @@ -111,9 +234,111 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) else if (mode->CrtcVDisplay > 480) pReg->tridentRegs3CE[CyberEnhance] |= 0x10; + OUTB(0x3CE, CyberControl); - if (!pTrident->CyberShadow) - pReg->tridentRegs3CE[CyberControl] = INB(0x3CF) & 0x7E; + pReg->tridentRegs3CE[CyberControl] = INB(0x3CF); + + OUTB(0x3CE,HorStretch); + pReg->tridentRegs3CE[HorStretch] = INB(0x3CF); + OUTB(0x3CE,VertStretch); + pReg->tridentRegs3CE[VertStretch] = INB(0x3CF); + + if ((!((pReg->tridentRegs3CE[VertStretch] & 1) || + (pReg->tridentRegs3CE[HorStretch] & 1))) + && (!LCDActive || ShadowModeActive)) { + unsigned char tmp; + + SHADOW_ENABLE(tmp); + OUTB(vgaIOBase + 4,0); + pReg->tridentRegs3x4[0x0] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,3); + pReg->tridentRegs3x4[0x3] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,4); + pReg->tridentRegs3x4[0x4] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,5); + pReg->tridentRegs3x4[0x5] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,0x6); + pReg->tridentRegs3x4[0x6] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,0x7); + pReg->tridentRegs3x4[0x7] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,0x10); + pReg->tridentRegs3x4[0x10] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,0x11); + pReg->tridentRegs3x4[0x11] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,0x16); + pReg->tridentRegs3x4[0x16] = INB(vgaIOBase + 5); + SHADOW_RESTORE(tmp); + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Timing shadow registers:" + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x\n",pReg->tridentRegs3x4[0], + pReg->tridentRegs3x4[3], pReg->tridentRegs3x4[4], + pReg->tridentRegs3x4[5], pReg->tridentRegs3x4[6], + pReg->tridentRegs3x4[7], pReg->tridentRegs3x4[0x10], + pReg->tridentRegs3x4[0x11], + pReg->tridentRegs3x4[0x16]); + } else { + if ((i = pTrident->lcdMode)) { + pReg->tridentRegs3x4[0x0] = LCD[i].shadow_0; + pReg->tridentRegs3x4[0x3] = LCD[i].shadow_3; + pReg->tridentRegs3x4[0x4] = LCD[i].shadow_4; + pReg->tridentRegs3x4[0x5] = LCD[i].shadow_5; + pReg->tridentRegs3x4[0x6] = LCD[i].shadow_6; + pReg->tridentRegs3x4[0x7] = LCD[i].shadow_7; + pReg->tridentRegs3x4[0x10] = LCD[i].shadow_10; + pReg->tridentRegs3x4[0x11] = LCD[i].shadow_11; + pReg->tridentRegs3x4[0x16] = LCD[i].shadow_16; + /* Not yet implemented */ + clock = LCD[i].clock; + } + } + /* copy over common bits from normal VGA */ + + pReg->tridentRegs3x4[0x7] &= ~0x52; + pReg->tridentRegs3x4[0x7] |= (vgaReg->CRTC[0x7] & 0x52); + + /* disable stretching, enable centering */ + pReg->tridentRegs3CE[VertStretch] &= 0xFE; + pReg->tridentRegs3CE[VertStretch] |= 0x80; + pReg->tridentRegs3CE[HorStretch] &= 0xFE; + pReg->tridentRegs3CE[HorStretch] |= 0x80; + + { + int mul = pScrn->bitsPerPixel >> 3; + int val; + + if (!mul) mul = 1; + + /* this is what my BIOS does */ + val = (pScrn->currentMode->HDisplay * mul / 8) + 16; + + pReg->tridentRegs3x4[PreEndControl] = 2 | ((val >> 8) & 1); + pReg->tridentRegs3x4[PreEndFetch] = val & 0xff; + } +#if 0 + OUTB(vgaIOBase + 4,PreEndControl); + pReg->tridentRegs3x4[PreEndControl] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,PreEndFetch); + pReg->tridentRegs3x4[PreEndFetch] = INB(vgaIOBase + 5); +#endif + /* set mode */ + pReg->tridentRegs3CE[BiosMode] = findMode(pScrn->currentMode->HDisplay, + pScrn->currentMode->VDisplay, + pScrn->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, "Setting BIOS Mode: %x\n", + pReg->tridentRegs3CE[BiosMode]); + + /* no stretch */ + pReg->tridentRegs3CE[BiosReg] = 0; + +#if 0 + /* obsolete */ + if (pTrident->CyberShadowSet) { + if (pTrident->CyberShadow) { + pReg->tridentRegs3CE[CyberControl] |= 0x81; + } else + pReg->tridentRegs3CE[CyberControl] &= 0x7E; + } +#endif } /* Defaults for all trident chipsets follows */ @@ -174,6 +399,7 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) } pReg->tridentRegs3C4[NewMode1] = 0xC0; + pReg->tridentRegs3C4[Protection] = 0x92; if (pTrident->Linear) pReg->tridentRegs3x4[LinearAddReg] = ((pTrident->FbAddress >> 24) << 6)| @@ -198,6 +424,8 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) pReg->tridentRegs3x4[Performance] = INB(vgaIOBase + 5) | 0x10; OUTB(vgaIOBase+ 4, DRAMControl); pReg->tridentRegs3x4[DRAMControl] = INB(vgaIOBase + 5) | 0x10; + if (pTrident->IsCyber && !pTrident->MMIOonly) + pReg->tridentRegs3x4[DRAMControl] |= 0x20; OUTB(vgaIOBase+ 4, AddColReg); pReg->tridentRegs3x4[AddColReg] = INB(vgaIOBase + 5) & 0xEF; pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4; @@ -224,8 +452,17 @@ TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) else pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF8; /* Enable PCI Bursting on capable chips */ - if (pTrident->Chipset >= TGUI9660) pReg->tridentRegs3x4[PCIReg] |= 0x06; - + if (pTrident->Chipset >= TGUI9660) { + if(pTrident->UsePCIBurst) { + pReg->tridentRegs3x4[PCIReg] |= 0x06; + } else { + pReg->tridentRegs3x4[PCIReg] &= 0xF9; + } + } + /* restore */ + OUTB(0x3C4, 0x11); + OUTB(0x3C5, protect); + return(TRUE); } @@ -238,13 +475,15 @@ TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) vgaHWGetIOBase(VGAHWPTR(pScrn)); vgaIOBase = VGAHWPTR(pScrn)->IOBase; + OUTB(0x3C4, Protection); + OUTB(0x3C5, 0x92); /* Goto New Mode */ OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Unprotect registers */ OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); - + temp = INB(0x3C8); temp = INB(0x3C6); temp = INB(0x3C6); @@ -272,8 +511,27 @@ TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) if (pTrident->Chipset >= PROVIDIA9685) OUTW_3x4(Enhancement0); if (pTrident->Chipset >= BLADE3D) OUTW_3x4(RAMDACTiming); if (pTrident->IsCyber) { + CARD8 tmp; + + OUTW_3CE(VertStretch); + OUTW_3CE(HorStretch); + OUTW_3CE(BiosMode); + OUTW_3CE(BiosReg); OUTW_3CE(CyberControl); OUTW_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + OUTW_3x4(0x0); + OUTW_3x4(0x3); + OUTW_3x4(0x4); + OUTW_3x4(0x5); + OUTW_3x4(0x6); + OUTW_3x4(0x7); + OUTW_3x4(0x10); + OUTW_3x4(0x11); + OUTW_3x4(0x96); + SHADOW_RESTORE(tmp); + OUTW_3x4(PreEndControl); + OUTW_3x4(PreEndFetch); } if (Is3Dchip) { @@ -293,6 +551,8 @@ TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) } OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]); + OUTB(0x3C4, Protection); + OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]); OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1] ^ 0x02) << 8)| NewMode1); } @@ -310,7 +570,8 @@ TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) temp = INB(0x3C5); INB_3C4(NewMode1); - + INB_3C4(Protection); + /* Unprotect registers */ OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); OUTW(vgaIOBase + 4, (0x92 << 8) | NewMode1); @@ -330,8 +591,26 @@ TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) if (pTrident->Chipset >= PROVIDIA9685) INB_3x4(Enhancement0); if (pTrident->Chipset >= BLADE3D) INB_3x4(RAMDACTiming); if (pTrident->IsCyber) { + CARD8 tmp; + INB_3CE(VertStretch); + INB_3CE(HorStretch); + INB_3CE(BiosMode); + INB_3CE(BiosReg); INB_3CE(CyberControl); INB_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + INB_3x4(0x0); + INB_3x4(0x3); + INB_3x4(0x4); + INB_3x4(0x5); + INB_3x4(0x6); + INB_3x4(0x7); + INB_3x4(0x10); + INB_3x4(0x11); + INB_3x4(0x16); + SHADOW_RESTORE(tmp); + INB_3x4(PreEndControl); + INB_3x4(PreEndFetch); } /* save cursor registers */ |