Home | History | Annotate | Line # | Download | only in src
      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 (at) 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 
     38 Bool
     39 TVGAInit(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 
    130 void
    131 TVGARestore(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 
    174 void
    175 TVGASave(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