tvga_dac.c revision 2378475a
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 "xf86PciInfo.h" 32#include "xf86Pci.h" 33 34#include "vgaHW.h" 35 36#include "trident.h" 37#include "trident_regs.h" 38 39Bool 40TVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 41{ 42 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 43 TRIDENTRegPtr pReg = &pTrident->ModeReg; 44 int vgaIOBase; 45 int offset = 0; 46 int clock = mode->Clock; 47 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 48 49 OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ 50 51 pReg->tridentRegsDAC[0x00] = 0x00; 52 OUTB(0x3C4, ConfPort2); 53 pReg->tridentRegs3C4[ConfPort2] = INB(0x3C5); 54 OUTB(0x3CE, MiscExtFunc); 55 pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0; 56 OUTB(vgaIOBase + 4, FIFOControl); 57 pReg->tridentRegs3x4[FIFOControl] = INB(vgaIOBase + 5) | 0x24; 58 59 /* YUK ! here we have to mess with old mode operation */ 60 OUTB(0x3C4, 0x0B); OUTB(0x3C5, 0x00); /* Goto Old Mode */ 61 OUTB(0x3C4, OldMode2 + NewMode2); 62 pReg->tridentRegs3C4[OldMode2] = 0x10; 63 OUTB(0x3C4, 0x0B); INB(0x3C5); /* Back to New Mode */ 64 pReg->tridentRegs3x4[Underline] = 0x40; 65 if (pTrident->Chipset < TGUI9440AGi) 66 pReg->tridentRegs3x4[CRTCMode] = 0xA3; 67 68 if (pScrn->videoRam > 512) 69 pReg->tridentRegs3C4[ConfPort2] |= 0x20; 70 else 71 pReg->tridentRegs3C4[ConfPort2] &= 0xDF; 72 73 switch (pScrn->bitsPerPixel) { 74 case 8: 75 if (pScrn->videoRam < 1024) 76 offset = pScrn->displayWidth >> 3; 77 else 78 offset = pScrn->displayWidth >> 4; 79 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 80 break; 81 case 16: 82 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 83 offset = pScrn->displayWidth >> 3; 84 /* Reload with any chipset specific stuff here */ 85 if (pTrident->Chipset == TVGA8900D) { 86 if (pScrn->depth == 15) 87 pReg->tridentRegsDAC[0x00] = 0xA0; 88 else 89 pReg->tridentRegsDAC[0x00] = 0xE0; 90 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Div by 2*/ 91 clock *= 2; /* Double the clock */ 92 } 93 break; 94 case 24: 95 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 96 offset = (pScrn->displayWidth * 3) >> 3; 97 pReg->tridentRegsDAC[0x00] = 0xD0; 98 break; 99 case 32: 100 pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; 101 pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Division by 2*/ 102 clock *= 2; /* Double the clock */ 103 offset = pScrn->displayWidth >> 1; 104 pReg->tridentRegsDAC[0x00] = 0x42; 105 break; 106 } 107 pReg->tridentRegs3x4[Offset] = offset & 0xFF; 108 109 pReg->tridentRegsClock[0x00] = mode->ClockIndex; 110 111 pReg->tridentRegs3C4[NewMode1] = 0x80; 112 113 if (LINEAR()) 114 pReg->tridentRegs3x4[LinearAddReg] = ((pTrident->FbAddress >> 24) << 6)| 115 ((pTrident->FbAddress >> 20) & 0x0F)| 116 0x20; 117 else { 118 pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; 119 pReg->tridentRegs3x4[LinearAddReg] = 0; 120 } 121 122 pReg->tridentRegs3x4[CRTCModuleTest] = 123 (mode->Flags & V_INTERLACE ? 0x84 : 0x80); 124 OUTB(vgaIOBase+ 4, AddColReg); 125 pReg->tridentRegs3x4[AddColReg] = (INB(vgaIOBase + 5) & 0xCF) | 126 ((offset & 0x100) >> 4); 127 128 return(TRUE); 129} 130 131void 132TVGARestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 133{ 134 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 135 int vgaIOBase; 136 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 137 138 /* Goto Old Mode */ 139 OUTB(0x3C4, 0x0B); 140 OUTB(0x3C5, 0x00); 141 OUTB(0x3C4, OldMode2 + NewMode2); 142 OUTB(0x3C5, tridentReg->tridentRegs3C4[OldMode2]); 143 144 /* Goto New Mode */ 145 OUTB(0x3C4, 0x0B); 146 (void) INB(0x3C5); 147 148 /* Unprotect registers */ 149 OUTW(0x3C4, (0x80 << 8) | NewMode1); 150 151 (void) INB(0x3C8); 152 (void) INB(0x3C6); 153 (void) INB(0x3C6); 154 (void) INB(0x3C6); 155 (void) INB(0x3C6); 156 OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); 157 (void) INB(0x3C8); 158 159 OUTW_3x4(CRTCModuleTest); 160 OUTW_3x4(LinearAddReg); 161 OUTW_3x4(FIFOControl); 162 OUTW_3C4(ConfPort2); 163 OUTW_3x4(Underline); 164 if (pTrident->Chipset < TGUI9440AGi) 165 OUTW_3x4(CRTCMode); 166 OUTW_3x4(AddColReg); 167 OUTW_3CE(MiscExtFunc); 168 OUTW_3x4(Offset); 169 170 TRIDENTClockSelect(pScrn, tridentReg->tridentRegsClock[0x00]); 171 172 OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1]) << 8)| NewMode1); 173} 174 175void 176TVGASave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) 177{ 178 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 179 int vgaIOBase; 180 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 181 182 (void) INB(0x3C8); 183 (void) INB(0x3C6); 184 (void) INB(0x3C6); 185 (void) INB(0x3C6); 186 (void) INB(0x3C6); 187 tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); 188 (void) INB(0x3C8); 189 190 /* Goto Old Mode */ 191 OUTB(0x3C4, 0x0B); 192 OUTB(0x3C5, 0x00); 193 OUTB(0x3C4, OldMode2 + NewMode2); 194 tridentReg->tridentRegs3C4[OldMode2] = INB(0x3C5); 195 196 /* Goto New Mode */ 197 OUTB(0x3C4, 0x0B); 198 (void) INB(0x3C5); 199 200 INB_3C4(NewMode1); 201 202 /* Unprotect registers */ 203 OUTW(0x3C4, ((0x80 ^ 0x02) << 8) | NewMode1); 204 OUTW(vgaIOBase + 4, (0x92 << 8) | NewMode1); 205 206 INB_3x4(Underline); 207 if (pTrident->Chipset < TGUI9440AGi) 208 INB_3x4(CRTCMode); 209 INB_3x4(LinearAddReg); 210 INB_3x4(FIFOControl); 211 INB_3x4(CRTCModuleTest); 212 INB_3x4(AddColReg); 213 INB_3CE(MiscExtFunc); 214 INB_3C4(ConfPort2); 215 216 TRIDENTClockSelect(pScrn, CLK_REG_SAVE); 217 218 /* Protect registers */ 219 OUTW_3C4(NewMode1); 220} 221