diff options
Diffstat (limited to 'driver/xf86-video-trident/src/trident_dac.c')
-rw-r--r-- | driver/xf86-video-trident/src/trident_dac.c | 1277 |
1 files changed, 1277 insertions, 0 deletions
diff --git a/driver/xf86-video-trident/src/trident_dac.c b/driver/xf86-video-trident/src/trident_dac.c new file mode 100644 index 000000000..1324ddfc1 --- /dev/null +++ b/driver/xf86-video-trident/src/trident_dac.c @@ -0,0 +1,1277 @@ +/* + * 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 + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dac.c,v 1.79 2003/11/03 05:11:42 tsi Exp $ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "vgaHW.h" + +#include "trident.h" +#include "trident_regs.h" + + +static biosMode bios1[] = { + { 640, 480, 0x11 } +}; + +static 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 } +}; + +static biosMode bios8[] = { + { 320, 200, 0x13 }, + { 640, 400, 0x5c }, + { 640, 480, 0x5d }, + { 720, 480, 0x60 }, + { 800, 600, 0x5e }, + { 1024, 768, 0x62 }, + { 1280, 1024, 0x64 }, + { 1600, 1200, 0x66 } +}; + +static biosMode bios15[] = { + { 640, 400, 0x72 }, + { 640, 480, 0x74 }, + { 720, 480, 0x70 }, + { 800, 600, 0x76 }, + { 1024, 768, 0x78 }, + { 1280, 1024, 0x7a }, + { 1600, 1200, 0x7c } +}; + +static biosMode bios16[] = { + { 640, 400, 0x73 }, + { 640, 480, 0x75 }, + { 720, 480, 0x71 }, + { 800, 600, 0x77 }, + { 1024, 768, 0x79 }, + { 1280, 1024, 0x7b }, + { 1600, 1200, 0x7d } +}; + +static biosMode bios24[] = { + { 640, 400, 0x6b }, + { 640, 480, 0x6c }, + { 720, 480, 0x61 }, + { 800, 600, 0x6d }, + { 1024, 768, 0x6e } +}; + +static newModes newModeRegs [] = { + { 320, 200, 0x13, 0x30 }, + { 640, 480, 0x13, 0x61 }, + { 800, 600, 0x13, 0x62 }, + { 1024, 768, 0x31, 0x63 }, + { 1280, 1024, 0x7b, 0x64 }, + { 1400, 1050, 0x11, 0x7b } +}; + +int +TridentFindMode(int xres, int yres, int depth) +{ + int xres_s; + int i, size; + biosMode *mode; + + switch (depth) { + 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; +} + +static void +TridentFindNewMode(int xres, int yres, CARD8 *gr5a, CARD8 *gr5c) +{ + int xres_s; + int i, size; + + size = sizeof(newModeRegs) / sizeof(newModes); + + for (i = 0; i < size; i++) { + if (xres <= newModeRegs[i].x_res) { + xres_s = newModeRegs[i].x_res; + for (; i < size; i++) { + if (newModeRegs[i].x_res != xres_s + || yres <= newModeRegs[i].y_res) { + *gr5a = newModeRegs[i].GR5a; + *gr5c = newModeRegs[i].GR5c; + return; + } + } + } + } + *gr5a = newModeRegs[size - 1].GR5a; + *gr5c = newModeRegs[size - 1].GR5c; + return; +} + +static void +tridentSetBrightnessAndGamma(TRIDENTRegPtr tridentReg, + Bool on, double exp,int brightness) +{ + int pivots[] = {0,3,15,63,255}; + + double slope; + double y_0; + double x, x_prev = 0, y, y_prev = 0; + int i; + CARD8 i_slopes[4]; + CARD8 intercepts[4]; + + if (!on) { + tridentReg->tridentRegs3C4[0xB4] &= ~0x80; + return; + } + + for (i = 0; i < 4; i++) { + x = pivots[i + 1] / 255.0; + y = pow(x,exp); + slope = (y - y_prev) / (x - x_prev); + y_0 = y - x * slope; + { +#define RND(x) ((((x) - (int) (x)) < 0.5) ? (int)(x) : (int)(x) + 1) + int val = slope; + if (val > 7) + i_slopes[i] = (3 << 4) | (RND(slope) & 0xf); + else if (val > 3) + i_slopes[i] = (2 << 4) | (RND(slope * 2) & 0xf); + else if (val > 1) + i_slopes[i] = (1 << 4) | (RND(slope * 4) & 0xf); + else + i_slopes[i] = (RND(slope * 8) & 0xf); +#undef RND + } + intercepts[i] = (char)(y_0 * 256 / 4); + x_prev = x; + y_prev = y; + } + + tridentReg->tridentRegs3C4[0xB4] = 0x80 | i_slopes[0]; + tridentReg->tridentRegs3C4[0xB5] = i_slopes[1]; + tridentReg->tridentRegs3C4[0xB6] = i_slopes[2]; + tridentReg->tridentRegs3C4[0xB7] = i_slopes[3]; + tridentReg->tridentRegs3C4[0xB8] = (intercepts[0] + brightness); + tridentReg->tridentRegs3C4[0xB9] = (intercepts[1] + brightness); + tridentReg->tridentRegs3C4[0xBA] = (intercepts[2] + brightness); + tridentReg->tridentRegs3C4[0xBB] = (intercepts[3] + brightness); +} + +Bool +TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTRegPtr pReg = &pTrident->ModeReg; + + int vgaIOBase; + int offset = 0; + int clock = pTrident->currentClock; + CARD8 protect = 0; + Bool fullSize = FALSE; + + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr regp = &hwp->ModeReg; + vgaRegPtr vgaReg = &hwp->ModeReg; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* Unprotect */ + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + protect = INB(0x3C5); + OUTB(0x3C5, 0x92); + } + + OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ + + pReg->tridentRegs3x4[PixelBusReg] = 0x00; + pReg->tridentRegsDAC[0x00] = 0x00; + pReg->tridentRegs3C4[NewMode2] = 0x20; + OUTB(0x3CE, MiscExtFunc); + pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0; + pReg->tridentRegs3x4[GraphEngReg] = 0x00; + pReg->tridentRegs3x4[PreEndControl] = 0; + pReg->tridentRegs3x4[PreEndFetch] = 0; + + pReg->tridentRegs3x4[CRTHiOrd] = (((mode->CrtcVBlankEnd-1) & 0x400)>>4) | + (((mode->CrtcVTotal - 2) & 0x400) >> 3) | + ((mode->CrtcVSyncStart & 0x400) >> 5) | + (((mode->CrtcVDisplay - 1) & 0x400) >> 6)| + 0x08; + + pReg->tridentRegs3x4[HorizOverflow] = ((mode->CrtcHTotal & 0x800) >> 11) | + ((mode->CrtcHBlankStart & 0x800)>>7); + + if (pTrident->IsCyber) { + Bool LCDActive; +#ifdef READOUT + Bool ShadowModeActive; +#endif + int i = pTrident->lcdMode; +#ifdef READOUT + OUTB(0x3CE, CyberControl); + ShadowModeActive = ((INB(0x3CF) & 0x81) == 0x81); +#endif + OUTB(0x3CE, FPConfig); + pReg->tridentRegs3CE[FPConfig] = INB(0x3CF); + if (pTrident->dspOverride) { + if (pTrident->dspOverride & LCD_ACTIVE) { + pReg->tridentRegs3CE[FPConfig] |= 0x10; + LCDActive = TRUE; + } else { + pReg->tridentRegs3CE[FPConfig] &= ~0x10; + LCDActive = FALSE; + } + if (pTrident->dspOverride & CRT_ACTIVE) + pReg->tridentRegs3CE[FPConfig] |= 0x20; + else + pReg->tridentRegs3CE[FPConfig] &= ~0x20; + } else { + LCDActive = (pReg->tridentRegs3CE[FPConfig] & 0x10); + } + + OUTB(0x3CE, CyberEnhance); +#if 0 + pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF); +#else + pReg->tridentRegs3CE[CyberEnhance] = INB(0x3CF) & 0x8F; + if (mode->CrtcVDisplay > 1024) + pReg->tridentRegs3CE[CyberEnhance] |= 0x50; + else + if (mode->CrtcVDisplay > 768) + pReg->tridentRegs3CE[CyberEnhance] |= 0x30; + else + if (mode->CrtcVDisplay > 600) + pReg->tridentRegs3CE[CyberEnhance] |= 0x20; + else + if (mode->CrtcVDisplay > 480) + pReg->tridentRegs3CE[CyberEnhance] |= 0x10; +#endif + OUTB(0x3CE, CyberControl); + pReg->tridentRegs3CE[CyberControl] = INB(0x3CF); + + OUTB(0x3CE,HorStretch); + pReg->tridentRegs3CE[HorStretch] = INB(0x3CF); + OUTB(0x3CE,VertStretch); + pReg->tridentRegs3CE[VertStretch] = INB(0x3CF); + +#ifdef READOUT + 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); + SHADOW_RESTORE(tmp); + } else +#endif + { + if (i != 0xff) { + pReg->tridentRegs3x4[0x0] = LCD[i].shadow_0; + pReg->tridentRegs3x4[0x1] = regp->CRTC[1]; + pReg->tridentRegs3x4[0x2] = regp->CRTC[2]; + 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; + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1, + "Overriding Horizontal timings.\n"); + } + } + + if (i != 0xff) { + pReg->tridentRegs3x4[0x7] = LCD[i].shadow_7; + pReg->tridentRegs3x4[0x10] = LCD[i].shadow_10; + pReg->tridentRegs3x4[0x11] = LCD[i].shadow_11; + pReg->tridentRegs3x4[0x12] = regp->CRTC[0x12]; + pReg->tridentRegs3x4[0x15] = regp->CRTC[0x15]; + pReg->tridentRegs3x4[0x16] = LCD[i].shadow_16; + if (LCDActive) { + /* use current screen size not panel size for display area */ + pReg->tridentRegs3x4[CRTHiOrd] = + (pReg->tridentRegs3x4[CRTHiOrd] & 0x10) + | (LCD[i].shadow_HiOrd & ~0x10); + } + + fullSize = (mode->HDisplay == LCD[i].display_x) + && (mode->VDisplay == LCD[i].display_y); + } + + /* copy over common bits from normal VGA */ + + pReg->tridentRegs3x4[0x7] &= ~0x4A; + pReg->tridentRegs3x4[0x7] |= (vgaReg->CRTC[0x7] & 0x4A); + if (LCDActive && fullSize) { + regp->CRTC[0] = pReg->tridentRegs3x4[0]; + regp->CRTC[3] = pReg->tridentRegs3x4[3]; + regp->CRTC[4] = pReg->tridentRegs3x4[4]; + regp->CRTC[5] = pReg->tridentRegs3x4[5]; + regp->CRTC[6] = pReg->tridentRegs3x4[6]; + regp->CRTC[7] = pReg->tridentRegs3x4[7]; + regp->CRTC[0x10] = pReg->tridentRegs3x4[0x10]; + regp->CRTC[0x11] = pReg->tridentRegs3x4[0x11]; + regp->CRTC[0x16] = pReg->tridentRegs3x4[0x16]; + } + if (LCDActive && !fullSize) { + /* + * Set negative h/vsync polarity to center display nicely + * Seems to work on several systems. + */ + regp->MiscOutReg |= 0xC0; + /* + * If the LCD is active and we don't fill the entire screen + * and the previous mode was stretched we may need help from + * the BIOS to set all registers for the unstreched mode. + */ + pTrident->doInit = ((pReg->tridentRegs3CE[HorStretch] & 1) + || (pReg->tridentRegs3CE[VertStretch] & 1)); + pReg->tridentRegs3CE[CyberControl] |= 0x81; + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow on\n"); + } else { + pReg->tridentRegs3CE[CyberControl] &= 0x7E; + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Shadow off\n"); + } + if (pTrident->FPDelay < 6) { + pReg->tridentRegs3CE[CyberControl] &= 0xC7; + pReg->tridentRegs3CE[CyberControl] |= (pTrident->FPDelay + 2) << 3; + } + + if (pTrident->CyberShadow) { + pReg->tridentRegs3CE[CyberControl] &= 0x7E; + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Forcing Shadow off\n"); + } + + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing shadow registers:" + " 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]); + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"H-timing registers: " + " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", + regp->CRTC[0], regp->CRTC[1], regp->CRTC[2], + regp->CRTC[3], regp->CRTC[4], regp->CRTC[5]); + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing shadow registers: " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x" + " 0x%2.2x (0x%2.2x)\n", + pReg->tridentRegs3x4[6], pReg->tridentRegs3x4[7], + pReg->tridentRegs3x4[0x10],pReg->tridentRegs3x4[0x11], + pReg->tridentRegs3x4[0x16], + pReg->tridentRegs3x4[CRTHiOrd]); + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"V-timing registers: " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x\n", + regp->CRTC[6], regp->CRTC[7], regp->CRTC[0x10], + regp->CRTC[0x11],regp->CRTC[0x12], + regp->CRTC[0x14],regp->CRTC[0x16]); + + + /* disable stretching, enable centering for default sizes */ + pReg->tridentRegs3CE[VertStretch] &= 0x7C; + switch (mode->VDisplay) { + case 768: + case 600: + case 480: + case 240: + pReg->tridentRegs3CE[VertStretch] |= 0x80; + } + pReg->tridentRegs3CE[HorStretch] &= 0x7C; + switch (mode->HDisplay) { + case 1024: + case 800: + case 640: + case 320: + pReg->tridentRegs3CE[HorStretch] |= 0x80; + } +#if 1 + { + int mul = pScrn->bitsPerPixel >> 3; + int val; + + if (!mul) mul = 1; + + /* this is what my BIOS does */ + val = (mode->HDisplay * mul / 8) + 16; + + pReg->tridentRegs3x4[PreEndControl] = ((val >> 8) < 2 ? 2 :0) + | ((val >> 8) & 0x01); + pReg->tridentRegs3x4[PreEndFetch] = val & 0xff; + } +#else + OUTB(vgaIOBase + 4,PreEndControl); + pReg->tridentRegs3x4[PreEndControl] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4,PreEndFetch); + pReg->tridentRegs3x4[PreEndFetch] = INB(vgaIOBase + 5); +#endif + /* set mode */ + if (pTrident->Chipset < BLADEXP) { + pReg->tridentRegs3CE[BiosMode] = TridentFindMode( + mode->HDisplay, + mode->VDisplay, + pScrn->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, + "Setting BIOS Mode: %x for: %ix%i\n", + pReg->tridentRegs3CE[BiosMode], + mode->HDisplay, + mode->VDisplay); + } else { + TridentFindNewMode(mode->HDisplay, + mode->VDisplay, + &pReg->tridentRegs3CE[BiosNewMode1], + &pReg->tridentRegs3CE[BiosNewMode2]); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, + "Setting BIOS Mode Regs: %x %x for: %ix%i\n", + pReg->tridentRegs3CE[BiosNewMode1], + pReg->tridentRegs3CE[BiosNewMode2], + mode->HDisplay, + mode->VDisplay); + }; + + /* no stretch */ + if (pTrident->Chipset == CYBERBLADEXPAI1 + || pTrident->Chipset == BLADEXP) + pReg->tridentRegs3CE[BiosReg] = 8; + else + pReg->tridentRegs3CE[BiosReg] = 0; + + if (pTrident->CyberStretch) { + pReg->tridentRegs3CE[VertStretch] |= 0x01; + pReg->tridentRegs3CE[HorStretch] |= 0x01; + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1,"Enabling StretchMode\n"); + } + } + + /* Enable Chipset specific options */ + switch (pTrident->Chipset) { + case XP5: + case CYBERBLADEXP4: + case CYBERBLADEXPAI1: + case BLADEXP: + case CYBERBLADEI7: + case CYBERBLADEI7D: + case CYBERBLADEI1: + case CYBERBLADEI1D: + case CYBERBLADEAI1: + case CYBERBLADEAI1D: + case CYBERBLADEE4: + case BLADE3D: + OUTB(vgaIOBase + 4, RAMDACTiming); + pReg->tridentRegs3x4[RAMDACTiming] = INB(vgaIOBase + 5) | 0x0F; + /* Fall Through */ + case CYBER9520: + case CYBER9525DVD: + case CYBER9397DVD: + case CYBER9397: + case IMAGE975: + case IMAGE985: + case CYBER9388: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x10; + if (!pReg->tridentRegs3x4[PreEndControl]) + pReg->tridentRegs3x4[PreEndControl] = 0x01; + if (!pReg->tridentRegs3x4[PreEndFetch]) + pReg->tridentRegs3x4[PreEndFetch] = 0xFF; + /* Fall Through */ + case PROVIDIA9685: + case CYBER9385: + pReg->tridentRegs3x4[Enhancement0] = 0x40; + /* Fall Through */ + case PROVIDIA9682: + case CYBER9382: + if (pTrident->UsePCIRetry) + pReg->tridentRegs3x4[PCIRetry] = 0xDF; + else + pReg->tridentRegs3x4[PCIRetry] = 0x1F; + /* Fall Through */ + case TGUI9660: + case TGUI9680: + if (pTrident->MUX && pScrn->bitsPerPixel == 8) { + pReg->tridentRegs3x4[PixelBusReg] |= 0x01; /* 16bit bus */ + pReg->tridentRegs3C4[NewMode2] |= 0x02; /* half clock */ + pReg->tridentRegsDAC[0x00] |= 0x20; /* mux mode */ + } + } + + /* Defaults for all trident chipsets follows */ + switch (pScrn->bitsPerPixel) { + case 8: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = pScrn->displayWidth >> 3; + break; + case 16: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = pScrn->displayWidth >> 2; + if (pScrn->depth == 15) + pReg->tridentRegsDAC[0x00] = 0x10; + else + pReg->tridentRegsDAC[0x00] = 0x30; + pReg->tridentRegs3x4[PixelBusReg] = 0x04; + /* Reload with any chipset specific stuff here */ + if (pTrident->Chipset >= TGUI9660) + pReg->tridentRegs3x4[PixelBusReg] |= 0x01; + if (pTrident->Chipset == TGUI9440AGi) { + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;/*Clock Division / 2*/ + clock *= 2; /* Double the clock */ + } + break; + case 24: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = (pScrn->displayWidth * 3) >> 3; + pReg->tridentRegs3x4[PixelBusReg] = 0x29; + pReg->tridentRegsDAC[0x00] = 0xD0; + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5 || + pTrident->Chipset == CYBERBLADEE4) { + OUTB(vgaIOBase+ 4, New32); + pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) & 0x7F; + } + break; + case 32: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + if (pTrident->Chipset != CYBERBLADEXP4 + && pTrident->Chipset != BLADEXP + && pTrident->Chipset != XP5 + && pTrident->Chipset != CYBERBLADEE4 + && pTrident->Chipset != CYBERBLADEXPAI1) { + /* Clock Division by 2*/ + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; + clock *= 2; /* Double the clock */ + } + offset = pScrn->displayWidth >> 1; + pReg->tridentRegs3x4[PixelBusReg] = 0x09; + pReg->tridentRegsDAC[0x00] = 0xD0; + if (pTrident->Chipset == CYBERBLADEXP4 + || pTrident->Chipset == BLADEXP + || pTrident->Chipset == XP5 + || pTrident->Chipset == CYBERBLADEE4 + || pTrident->Chipset == CYBERBLADEXPAI1) { + OUTB(vgaIOBase+ 4, New32); + pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) | 0x80; + /* With new mode 32bpp we set the packed flag */ + pReg->tridentRegs3x4[PixelBusReg] |= 0x20; + } + break; + } + pReg->tridentRegs3x4[Offset] = offset & 0xFF; + + { + CARD8 a, b; + TGUISetClock(pScrn, clock, &a, &b); + pReg->tridentRegsClock[0x00] = (regp->MiscOutReg & 0xF3) | 0x08; + pReg->tridentRegsClock[0x01] = a; + pReg->tridentRegsClock[0x02] = b; + if (pTrident->MCLK > 0) { + TGUISetMCLK(pScrn, pTrident->MCLK, &a, &b); + pReg->tridentRegsClock[0x03] = a; + pReg->tridentRegsClock[0x04] = b; + } + } + + pReg->tridentRegs3C4[NewMode1] = 0xC0; + pReg->tridentRegs3C4[Protection] = 0x92; + + pReg->tridentRegs3x4[LinearAddReg] = 0; + if (pTrident->Linear) { + /* This is used for VLB, when we support it again in 4.0 */ + if (pTrident->Chipset < CYBER9385) + pReg->tridentRegs3x4[LinearAddReg] |= + ((pTrident->FbAddress >> 24) << 6)| + ((pTrident->FbAddress >> 20) & 0x0F); + /* Turn on linear mapping */ + pReg->tridentRegs3x4[LinearAddReg] |= 0x20; + } else { + pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; + } + + pReg->tridentRegs3x4[CRTCModuleTest] = + (mode->Flags & V_INTERLACE ? 0x84 : 0x80); + + OUTB(vgaIOBase+ 4, InterfaceSel); + pReg->tridentRegs3x4[InterfaceSel] = INB(vgaIOBase + 5) | 0x40; + + OUTB(vgaIOBase+ 4, Performance); + pReg->tridentRegs3x4[Performance] = INB(vgaIOBase + 5); + if (pTrident->Chipset < BLADEXP) + pReg->tridentRegs3x4[Performance] |= 0x10; + + OUTB(vgaIOBase+ 4, DRAMControl); + if (pTrident->Chipset >= CYBER9388) + pReg->tridentRegs3x4[DRAMControl] = INB(vgaIOBase + 5) | 0x10; + + if (pTrident->IsCyber && !pTrident->MMIOonly) + pReg->tridentRegs3x4[DRAMControl] |= 0x20; + + if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) { + OUTB(vgaIOBase + 4, ClockControl); + pReg->tridentRegs3x4[ClockControl] = INB(vgaIOBase + 5) | 0x01; + } + + OUTB(vgaIOBase+ 4, AddColReg); + pReg->tridentRegs3x4[AddColReg] = INB(vgaIOBase + 5) & 0xEF; + pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4; + + if (pTrident->Chipset >= TGUI9660) { + pReg->tridentRegs3x4[AddColReg] &= 0xDF; + pReg->tridentRegs3x4[AddColReg] |= (offset & 0x200) >> 4; + } + + if (IsPciCard && UseMMIO) { + if (!pTrident->NoAccel) + pReg->tridentRegs3x4[GraphEngReg] |= 0x80; + } else { + if (!pTrident->NoAccel) + pReg->tridentRegs3x4[GraphEngReg] |= 0x82; + } + + OUTB(0x3CE, MiscIntContReg); + pReg->tridentRegs3CE[MiscIntContReg] = INB(0x3CF) | 0x04; + + /* Fix hashing problem in > 8bpp on 9320 chipset */ + if (pTrident->Chipset == CYBER9320 && pScrn->bitsPerPixel > 8) + pReg->tridentRegs3CE[MiscIntContReg] &= ~0x80; + + OUTB(vgaIOBase+ 4, PCIReg); + if (IsPciCard && UseMMIO) + pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF9; + else + pReg->tridentRegs3x4[PCIReg] = INB(vgaIOBase + 5) & 0xF8; + + /* Enable PCI Bursting on capable chips */ + if (pTrident->Chipset >= TGUI9660) { + if(pTrident->UsePCIBurst) { + pReg->tridentRegs3x4[PCIReg] |= 0x06; + } else { + pReg->tridentRegs3x4[PCIReg] &= 0xF9; + } + } + + if (pTrident->Chipset >= CYBER9388) { + if (pTrident->GammaBrightnessOn) + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,1, + "Setting Gamma: %f Brightness: %i\n", + pTrident->gamma, pTrident->brightness); + tridentSetBrightnessAndGamma(pReg, + pTrident->GammaBrightnessOn, + pTrident->gamma, pTrident->brightness); + } + + /* Video */ + OUTB(0x3C4,0x20); + pReg->tridentRegs3C4[SSetup] = INB(0x3C5) | 0x4; + pReg->tridentRegs3C4[SKey] = 0x00; + pReg->tridentRegs3C4[SPKey] = 0xC0; + OUTB(0x3C4,0x12); + pReg->tridentRegs3C4[Threshold] = INB(0x3C5); + if (pScrn->bitsPerPixel > 16) + pReg->tridentRegs3C4[Threshold] = + (pReg->tridentRegs3C4[Threshold] & 0xf0) | 0x2; + + /* restore */ + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, protect); + } + + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5) + pReg->tridentRegs3CE[DisplayEngCont] = 0x08; + + /* Avoid lockup on Blade3D, PCI Retry is permanently on */ + if (pTrident->Chipset == BLADE3D) + pReg->tridentRegs3x4[PCIRetry] = 0x9F; + + return(TRUE); +} + +void +TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, 0x92); + } +#if 0 + if (pTrident->doInit && pTrident->Int10) { + OUTW_3CE(BiosReg); + } +#endif + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + (void) INB(0x3C5); + + /* Unprotect registers */ + OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); + + (void) INB(0x3C8); + (void) INB(0x3C6); + (void) INB(0x3C6); + (void) INB(0x3C6); + (void) INB(0x3C6); + OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); + (void) INB(0x3C8); + + OUTW_3x4(CRTCModuleTest); + OUTW_3x4(LinearAddReg); + OUTW_3C4(NewMode2); + OUTW_3x4(CursorControl); + OUTW_3x4(CRTHiOrd); + OUTW_3x4(HorizOverflow); + OUTW_3x4(AddColReg); + OUTW_3x4(GraphEngReg); + OUTW_3x4(Performance); + OUTW_3x4(InterfaceSel); + OUTW_3x4(DRAMControl); + OUTW_3x4(PixelBusReg); + OUTW_3x4(PCIReg); + OUTW_3x4(PCIRetry); + OUTW_3CE(MiscIntContReg); + OUTW_3CE(MiscExtFunc); + OUTW_3x4(Offset); + if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) + OUTW_3x4(ClockControl); + if (pTrident->Chipset >= CYBER9388) { + OUTW_3C4(Threshold); + OUTW_3C4(SSetup); + OUTW_3C4(SKey); + OUTW_3C4(SPKey); + OUTW_3x4(PreEndControl); + OUTW_3x4(PreEndFetch); + OUTW_3C4(GBslope1); + OUTW_3C4(GBslope2); + OUTW_3C4(GBslope3); + OUTW_3C4(GBslope4); + OUTW_3C4(GBintercept1); + OUTW_3C4(GBintercept2); + OUTW_3C4(GBintercept3); + OUTW_3C4(GBintercept4); + } + if (pTrident->Chipset >= CYBER9385) OUTW_3x4(Enhancement0); + if (pTrident->Chipset >= BLADE3D) OUTW_3x4(RAMDACTiming); + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5 || + pTrident->Chipset == CYBERBLADEE4) OUTW_3x4(New32); + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5) OUTW_3CE(DisplayEngCont); + if (pTrident->IsCyber) { + CARD8 tmp; + + OUTW_3CE(VertStretch); + OUTW_3CE(HorStretch); + if (pTrident->Chipset < BLADEXP) { + OUTW_3CE(BiosMode); + } else { + OUTW_3CE(BiosNewMode1); + OUTW_3CE(BiosNewMode2); + }; + OUTW_3CE(BiosReg); + OUTW_3CE(FPConfig); + OUTW_3CE(CyberControl); + OUTW_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + OUTW_3x4(0x0); + if (pTrident->shadowNew) { + OUTW_3x4(0x1); + OUTW_3x4(0x2); + } + OUTW_3x4(0x3); + OUTW_3x4(0x4); + OUTW_3x4(0x5); + OUTW_3x4(0x6); + OUTW_3x4(0x7); + OUTW_3x4(0x10); + OUTW_3x4(0x11); + if (pTrident->shadowNew) { + OUTW_3x4(0x12); + OUTW_3x4(0x15); + } + OUTW_3x4(0x16); + SHADOW_RESTORE(tmp); + } + + if (Is3Dchip) { +#ifdef READOUT + if (!pTrident->DontSetClock) +#endif + { + OUTW(0x3C4, (tridentReg->tridentRegsClock[0x01])<<8 | ClockLow); + OUTW(0x3C4, (tridentReg->tridentRegsClock[0x02])<<8 | ClockHigh); + } + if (pTrident->MCLK > 0) { + OUTW(0x3C4,(tridentReg->tridentRegsClock[0x03])<<8 | MCLKLow); + OUTW(0x3C4,(tridentReg->tridentRegsClock[0x04])<<8 | MCLKHigh); + } + } else { +#ifdef READOUT + if (!pTrident->DontSetClock) +#endif + { + OUTB(0x43C8, tridentReg->tridentRegsClock[0x01]); + OUTB(0x43C9, tridentReg->tridentRegsClock[0x02]); + } + if (pTrident->MCLK > 0) { + OUTB(0x43C6, tridentReg->tridentRegsClock[0x03]); + OUTB(0x43C7, tridentReg->tridentRegsClock[0x04]); + } + } +#ifdef READOUT + if (!pTrident->DontSetClock) +#endif + { + OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]); + } + + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]); + } + + OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1] ^ 0x02) << 8)| NewMode1); +} + +void +TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + (void) INB(0x3C5); + + INB_3C4(NewMode1); + if (pTrident->Chipset > PROVIDIA9685) + INB_3C4(Protection); + + /* Unprotect registers */ + OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); + if (pTrident->Chipset > PROVIDIA9685) + OUTW(0x3C4, (0x92 << 8) | Protection); + + INB_3x4(Offset); + INB_3x4(LinearAddReg); + INB_3x4(CRTCModuleTest); + INB_3x4(CRTHiOrd); + INB_3x4(HorizOverflow); + INB_3x4(Performance); + INB_3x4(InterfaceSel); + INB_3x4(DRAMControl); + INB_3x4(AddColReg); + INB_3x4(PixelBusReg); + INB_3x4(GraphEngReg); + INB_3x4(PCIReg); + INB_3x4(PCIRetry); + if (pTrident->NewClockCode && pTrident->Chipset <= CYBER9397DVD) + INB_3x4(ClockControl); + if (pTrident->Chipset >= CYBER9388) { + INB_3C4(Threshold); + INB_3C4(SSetup); + INB_3C4(SKey); + INB_3C4(SPKey); + INB_3x4(PreEndControl); + INB_3x4(PreEndFetch); + INB_3C4(GBslope1); + INB_3C4(GBslope2); + INB_3C4(GBslope3); + INB_3C4(GBslope4); + INB_3C4(GBintercept1); + INB_3C4(GBintercept2); + INB_3C4(GBintercept3); + INB_3C4(GBintercept4); + } + if (pTrident->Chipset >= CYBER9385) INB_3x4(Enhancement0); + if (pTrident->Chipset >= BLADE3D) INB_3x4(RAMDACTiming); + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5 || + pTrident->Chipset == CYBERBLADEE4) INB_3x4(New32); + if (pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == XP5) INB_3CE(DisplayEngCont); + if (pTrident->IsCyber) { + CARD8 tmp; + INB_3CE(VertStretch); + INB_3CE(HorStretch); + if (pTrident->Chipset < BLADEXP) { + INB_3CE(BiosMode); + } else { + INB_3CE(BiosNewMode1); + INB_3CE(BiosNewMode2); + } + INB_3CE(BiosReg); + INB_3CE(FPConfig); + INB_3CE(CyberControl); + INB_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + INB_3x4(0x0); + if (pTrident->shadowNew) { + INB_3x4(0x1); + INB_3x4(0x2); + } + INB_3x4(0x3); + INB_3x4(0x4); + INB_3x4(0x5); + INB_3x4(0x6); + INB_3x4(0x7); + INB_3x4(0x10); + INB_3x4(0x11); + if (pTrident->shadowNew) { + INB_3x4(0x12); + INB_3x4(0x15); + } + INB_3x4(0x16); + SHADOW_RESTORE(tmp); + } + + /* save cursor registers */ + INB_3x4(CursorControl); + + INB_3CE(MiscExtFunc); + INB_3CE(MiscIntContReg); + + (void) INB(0x3C8); + (void) INB(0x3C6); + (void) INB(0x3C6); + (void) INB(0x3C6); + (void) INB(0x3C6); + tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); + (void) INB(0x3C8); + + tridentReg->tridentRegsClock[0x00] = INB(0x3CC); + if (Is3Dchip) { + OUTB(0x3C4, ClockLow); + tridentReg->tridentRegsClock[0x01] = INB(0x3C5); + OUTB(0x3C4, ClockHigh); + tridentReg->tridentRegsClock[0x02] = INB(0x3C5); + if (pTrident->MCLK > 0) { + OUTB(0x3C4, MCLKLow); + tridentReg->tridentRegsClock[0x03] = INB(0x3C5); + OUTB(0x3C4, MCLKHigh); + tridentReg->tridentRegsClock[0x04] = INB(0x3C5); + } + } else { + tridentReg->tridentRegsClock[0x01] = INB(0x43C8); + tridentReg->tridentRegsClock[0x02] = INB(0x43C9); + if (pTrident->MCLK > 0) { + tridentReg->tridentRegsClock[0x03] = INB(0x43C6); + tridentReg->tridentRegsClock[0x04] = INB(0x43C7); + } + } + + INB_3C4(NewMode2); + + /* Protect registers */ + OUTW_3C4(NewMode1); +} + +static void +TridentShowCursor(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* 64x64 */ + OUTW(vgaIOBase + 4, 0xC150); +} + +static void +TridentHideCursor(ScrnInfoPtr pScrn) { + int vgaIOBase; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + OUTW(vgaIOBase + 4, 0x4150); +} + +static void +TridentSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + int vgaIOBase; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + if (x < 0) { + OUTW(vgaIOBase + 4, (-x)<<8 | 0x46); + x = 0; + } else + OUTW(vgaIOBase + 4, 0x0046); + + if (y < 0) { + OUTW(vgaIOBase + 4, (-y)<<8 | 0x47); + y = 0; + } else + OUTW(vgaIOBase + 4, 0x0047); + + OUTW(vgaIOBase + 4, (x&0xFF)<<8 | 0x40); + OUTW(vgaIOBase + 4, (x&0x0F00) | 0x41); + OUTW(vgaIOBase + 4, (y&0xFF)<<8 | 0x42); + OUTW(vgaIOBase + 4, (y&0x0F00) | 0x43); +} + +static void +TridentSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + int vgaIOBase; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + OUTW(vgaIOBase + 4, (fg & 0x000000FF)<<8 | 0x48); + OUTW(vgaIOBase + 4, (fg & 0x0000FF00) | 0x49); + OUTW(vgaIOBase + 4, (fg & 0x00FF0000)>>8 | 0x4A); + OUTW(vgaIOBase + 4, (fg & 0xFF000000)>>16 | 0x4B); + OUTW(vgaIOBase + 4, (bg & 0x000000FF)<<8 | 0x4C); + OUTW(vgaIOBase + 4, (bg & 0x0000FF00) | 0x4D); + OUTW(vgaIOBase + 4, (bg & 0x00FF0000)>>8 | 0x4E); + OUTW(vgaIOBase + 4, (bg & 0xFF000000)>>16 | 0x4F); +} + +static void +TridentLoadCursorImage( + ScrnInfoPtr pScrn, + CARD8 *src +) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase; + int programmed_offset = pTrident->CursorOffset / 1024; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + memcpy((CARD8 *)pTrident->FbBase + pTrident->CursorOffset, + src, pTrident->CursorInfoRec->MaxWidth * + pTrident->CursorInfoRec->MaxHeight / 4); + + OUTW(vgaIOBase + 4, ((programmed_offset & 0xFF) << 8) | 0x44); + OUTW(vgaIOBase + 4, (programmed_offset & 0xFF00) | 0x45); +} + +static Bool +TridentUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (pTrident->MUX && pScrn->bitsPerPixel == 8) return FALSE; + + if (!pTrident->HWCursor) return FALSE; + + return TRUE; +} + +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 +#define CURSOR_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) + +Bool +TridentHWCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + xf86CursorInfoPtr infoPtr; + FBAreaPtr fbarea; + int width; + int width_bytes; + int height; + int size_bytes; + + size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; + width = pScrn->displayWidth; + width_bytes = width * (pScrn->bitsPerPixel / 8); + height = (size_bytes + width_bytes - 1) / width_bytes; + fbarea = xf86AllocateOffscreenArea(pScreen, + width, + height, + 1024, + NULL, + NULL, + NULL); + + if (!fbarea) { + pTrident->CursorOffset = 0; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Hardware cursor disabled" + " due to insufficient offscreen memory\n"); + return FALSE; + } else { + pTrident->CursorOffset = CURSOR_ALIGN((fbarea->box.x1 + + fbarea->box.y1 * width) * + pScrn->bitsPerPixel / 8, + 1024); + } + + if ((pTrident->Chipset != CYBER9397DVD) && + (pTrident->Chipset < CYBERBLADEE4)) { + /* Can't deal with an offset more than 4MB - 4096 bytes */ + if (pTrident->CursorOffset >= ((4096*1024) - 4096)) { + pTrident->CursorOffset = 0; + xf86FreeOffscreenArea(fbarea); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Hardware cursor disabled" + " due to cursor offset constraints.\n"); + return FALSE; + } + } + + infoPtr = xf86CreateCursorInfoRec(); + if(!infoPtr) return FALSE; + + pTrident->CursorInfoRec = infoPtr; + + infoPtr->MaxWidth = 64; + infoPtr->MaxHeight = 64; + infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | + ((pTrident->Chipset == CYBERBLADEXP4 || + pTrident->Chipset == BLADEXP || + pTrident->Chipset == XP5 || + pTrident->Chipset == CYBERBLADEE4) ? + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP : 0); + infoPtr->SetCursorColors = TridentSetCursorColors; + infoPtr->SetCursorPosition = TridentSetCursorPosition; + infoPtr->LoadCursorImage = TridentLoadCursorImage; + infoPtr->HideCursor = TridentHideCursor; + infoPtr->ShowCursor = TridentShowCursor; + infoPtr->UseHWCursor = TridentUseHWCursor; + + return(xf86InitCursor(pScreen, infoPtr)); +} + +unsigned int +Tridentddc1Read(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + CARD8 temp; + + /* New mode */ + OUTB(0x3C4, 0x0B); temp = INB(0x3C5); + + OUTB(0x3C4, NewMode1); + temp = INB(0x3C5); + OUTB(0x3C5, temp | 0x80); + + /* Define SDA as input */ + OUTW(vgaIOBase + 4, (0x04 << 8) | I2C); + + OUTW(0x3C4, (temp << 8) | NewMode1); + + /* Wait until vertical retrace is in progress. */ + while (INB(vgaIOBase + 0xA) & 0x08); + while (!(INB(vgaIOBase + 0xA) & 0x08)); + + /* Get the result */ + OUTB(vgaIOBase + 4, I2C); + return ( INB(vgaIOBase + 5) & 0x01 ); +} + +void TridentSetOverscan( + ScrnInfoPtr pScrn, + int overscan +){ + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (overscan < 0 || overscan > 255) + return; + + hwp->enablePalette(hwp); + hwp->writeAttr(hwp, OVERSCAN, overscan); + hwp->disablePalette(hwp); +} + +void TridentLoadPalette( + ScrnInfoPtr pScrn, + int numColors, + int *indicies, + LOCO *colors, + VisualPtr pVisual +){ + vgaHWPtr hwp = VGAHWPTR(pScrn); + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int i, index; + for(i = 0; i < numColors; i++) { + index = indicies[i]; + OUTB(0x3C6, 0xFF); + DACDelay(hwp); + OUTB(0x3c8, index); + DACDelay(hwp); + OUTB(0x3c9, colors[index].red); + DACDelay(hwp); + OUTB(0x3c9, colors[index].green); + DACDelay(hwp); + OUTB(0x3c9, colors[index].blue); + DACDelay(hwp); + } +} |