1/* 2 * Copyright 1992-2003 by Alan Hourihane, North Wales, UK. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Alan Hourihane, alanh@fairlite.demon.co.uk 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "xf86Pci.h" 32 33#include "vgaHW.h" 34 35#include "trident.h" 36#include "trident_regs.h" 37 38Bool 39TVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 40{ 41 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 42 TRIDENTRegPtr pReg = &pTrident->ModeReg; 43 int vgaIOBase; 44 int offset = 0; 45 int clock = mode->Clock; 46 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 47 48 OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ 49 50 pReg->tridentRegsDAC[0x00] = 0x00; 51 OUTB(0x3C4, ConfPort2); 52 pReg->tridentRegs3C4[ConfPort2] = INB(0x3C5); 53 OUTB(0x3CE, MiscExtFunc); 54 pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0; 55 OUTB(vgaIOBase + 4, FIFOControl); 56 pReg->tridentRegs3x4[FIFOControl] = INB(vgaIOBase + 5) | 0x24; 57 58 /* YUK ! here we have to mess with old mode operation */ 59 OUTB(0x3C4, 0x0B); OUTB(0x3C5, 0x00); /* Goto Old Mode */ 60 OUTB(0x3C4, OldMode2 + NewMode2); 61 pReg->tridentRegs3C4[OldMode2] = 0x10; 62 OUTB(0x3C4, 0x0B); INB(0x3C5); /* Back to New Mode */ 63 pReg->tridentRegs3x4[Underline] = 0x40; 64 if (pTrident->Chipset < TGUI9440AGi) 65 pReg->tridentRegs3x4[CRTCMode] = 0xA3; 66 67 if (pScrn->videoRam > 512) 68 pReg->tridentRegs3C4[ConfPort2] |= 0x20; 69 else 70 pReg->tridentRegs3C4[ConfPort2] &= 0xDF; 71 72 switch (pScrn->bitsPerPixel) { 73 case 8: 74 if (pScrn->videoRam < 1024) 75 offset = pScrn->displayWidth >> 3; 76 else 77 offset = pScrn->displayWidth >> 4; 78 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 79 break; 80 case 16: 81 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 82 offset = pScrn->displayWidth >> 3; 83 /* Reload with any chipset specific stuff here */ 84 if (pTrident->Chipset == TVGA8900D) { 85 if (pScrn->depth == 15) 86 pReg->tridentRegsDAC[0x00] = 0xA0; 87 else 88 pReg->tridentRegsDAC[0x00] = 0xE0; 89 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Div by 2*/ 90 clock *= 2; /* Double the clock */ 91 } 92 break; 93 case 24: 94 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 95 offset = (pScrn->displayWidth * 3) >> 3; 96 pReg->tridentRegsDAC[0x00] = 0xD0; 97 break; 98 case 32: 99 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 100 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Division by 2*/ 101 clock *= 2; /* Double the clock */ 102 offset = pScrn->displayWidth >> 1; 103 pReg->tridentRegsDAC[0x00] = 0x42; 104 break; 105 } 106 pReg->tridentRegs3x4[Offset] = offset & 0xFF; 107 108 pReg->tridentRegsClock[0x00] = mode->ClockIndex; 109 110 pReg->tridentRegs3C4[NewMode1] = 0x80; 111 112 if (LINEAR()) 113 pReg->tridentRegs3x4[LinearAddReg] = ((pTrident->FbAddress >> 24) << 6)| 114 ((pTrident->FbAddress >> 20) & 0x0F)| 115 0x20; 116 else { 117 pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; 118 pReg->tridentRegs3x4[LinearAddReg] = 0; 119 } 120 121 pReg->tridentRegs3x4[CRTCModuleTest] = 122 (mode->Flags & V_INTERLACE ? 0x84 : 0x80); 123 OUTB(vgaIOBase+ 4, AddColReg); 124 pReg->tridentRegs3x4[AddColReg] = (INB(vgaIOBase + 5) & 0xCF) | 125 ((offset & 0x100) >> 4); 126 127 return(TRUE); 128} 129 130void 131TVGARestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 132{ 133 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 134 int vgaIOBase; 135 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 136 137 /* Goto Old Mode */ 138 OUTB(0x3C4, 0x0B); 139 OUTB(0x3C5, 0x00); 140 OUTB(0x3C4, OldMode2 + NewMode2); 141 OUTB(0x3C5, tridentReg->tridentRegs3C4[OldMode2]); 142 143 /* Goto New Mode */ 144 OUTB(0x3C4, 0x0B); 145 (void) INB(0x3C5); 146 147 /* Unprotect registers */ 148 OUTW(0x3C4, (0x80 << 8) | NewMode1); 149 150 (void) INB(0x3C8); 151 (void) INB(0x3C6); 152 (void) INB(0x3C6); 153 (void) INB(0x3C6); 154 (void) INB(0x3C6); 155 OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); 156 (void) INB(0x3C8); 157 158 OUTW_3x4(CRTCModuleTest); 159 OUTW_3x4(LinearAddReg); 160 OUTW_3x4(FIFOControl); 161 OUTW_3C4(ConfPort2); 162 OUTW_3x4(Underline); 163 if (pTrident->Chipset < TGUI9440AGi) 164 OUTW_3x4(CRTCMode); 165 OUTW_3x4(AddColReg); 166 OUTW_3CE(MiscExtFunc); 167 OUTW_3x4(Offset); 168 169 TRIDENTClockSelect(pScrn, tridentReg->tridentRegsClock[0x00]); 170 171 OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1]) << 8)| NewMode1); 172} 173 174void 175TVGASave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 176{ 177 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 178 int vgaIOBase; 179 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 180 181 (void) INB(0x3C8); 182 (void) INB(0x3C6); 183 (void) INB(0x3C6); 184 (void) INB(0x3C6); 185 (void) INB(0x3C6); 186 tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); 187 (void) INB(0x3C8); 188 189 /* Goto Old Mode */ 190 OUTB(0x3C4, 0x0B); 191 OUTB(0x3C5, 0x00); 192 OUTB(0x3C4, OldMode2 + NewMode2); 193 tridentReg->tridentRegs3C4[OldMode2] = INB(0x3C5); 194 195 /* Goto New Mode */ 196 OUTB(0x3C4, 0x0B); 197 (void) INB(0x3C5); 198 199 INB_3C4(NewMode1); 200 201 /* Unprotect registers */ 202 OUTW(0x3C4, ((0x80 ^ 0x02) << 8) | NewMode1); 203 OUTW(vgaIOBase + 4, (0x92 << 8) | NewMode1); 204 205 INB_3x4(Underline); 206 if (pTrident->Chipset < TGUI9440AGi) 207 INB_3x4(CRTCMode); 208 INB_3x4(LinearAddReg); 209 INB_3x4(FIFOControl); 210 INB_3x4(CRTCModuleTest); 211 INB_3x4(AddColReg); 212 INB_3CE(MiscExtFunc); 213 INB_3C4(ConfPort2); 214 215 TRIDENTClockSelect(pScrn, CLK_REG_SAVE); 216 217 /* Protect registers */ 218 OUTW_3C4(NewMode1); 219} 220