diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | b1d44d56b82021cf73fb3449faa9ddc4efd72a87 (patch) | |
tree | c69cdc593e0eb6e11d9f4b753c619ddd84a993ad |
Initial revision
-rw-r--r-- | man/trident.man | 125 | ||||
-rw-r--r-- | src/blade_accel.c | 704 | ||||
-rw-r--r-- | src/image_accel.c | 647 | ||||
-rw-r--r-- | src/trident.h | 346 | ||||
-rw-r--r-- | src/trident_accel.c | 673 | ||||
-rw-r--r-- | src/trident_bank.c | 95 | ||||
-rw-r--r-- | src/trident_dac.c | 1200 | ||||
-rw-r--r-- | src/trident_dga.c | 275 | ||||
-rw-r--r-- | src/trident_driver.c | 3632 | ||||
-rw-r--r-- | src/trident_i2c.c | 77 | ||||
-rw-r--r-- | src/trident_regs.h | 395 | ||||
-rw-r--r-- | src/trident_shadow.c | 260 | ||||
-rw-r--r-- | src/trident_video.c | 1408 | ||||
-rw-r--r-- | src/tridenthelper.c | 341 | ||||
-rw-r--r-- | src/tridentramdac.c | 67 | ||||
-rw-r--r-- | src/tvga_dac.c | 231 | ||||
-rw-r--r-- | src/xp_accel.c | 601 |
17 files changed, 11077 insertions, 0 deletions
diff --git a/man/trident.man b/man/trident.man new file mode 100644 index 0000000..a02fa43 --- /dev/null +++ b/man/trident.man @@ -0,0 +1,125 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident.man,v 1.12 2003/01/06 10:15:26 alanh Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH TRIDENT __drivermansuffix__ __vendorversion__ +.SH NAME +trident \- Trident video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qtrident\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B trident +is an XFree86 driver for Trident video cards. The driver is +accelerated, and provides support for the following framebuffer depths: +1, 4, 8, 15, 16, and 24. Multi-head configurations are supported. +The XvImage extension is supported on TGUI96xx and greater cards. +.SH SUPPORTED HARDWARE +The +.B trident +driver supports PCI,AGP and ISA video cards based on the following +Trident chips: +.TP 12 +.B Blade +Blade3D, CyberBlade series i1, i7 (DSTN), i1, i1 (DSTN), Ai1, Ai1 (DSTN), +CyberBlade/e4, CyberBladeXP, CyberBladeAi1/XP, BladeXP +.TP 12 +.B Image +3DImage975, 3DImage985, Cyber9520, Cyber9525, Cyber9397, Cyber9397DVD +.TP 12 +.B ProVidia +9682, 9685, Cyber9382, Cyber9385, Cyber9388 +.TP 12 +.B TGUI +9440AGi, 9660, 9680 +.TP 12 +.B ISA/VLBus +8900C, 8900D, 9000, 9200CXr, Cyber9320, 9400CXi, 9440AGi +These cards have been ported but need furthur testing and may not work. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.PP +The following driver +.B Options +are supported: +.TP +.BI "Option \*qSWCursor\*q \*q" boolean \*q +Enable or disable the SW cursor. Default: off. +.TP +.BI "Option \*qNoAccel\*q \*q" boolean \*q +Disable or enable acceleration. Default: acceleration is enabled. +.TP +.BI "Option \*qPciRetry\*q \*q" boolean \*q +Enable or disable PCI retries. Default: off. +.TP +.BI "Option \*qCyberShadow\*q \*q" boolean \*q +For Cyber chipsets only, turn off shadow registers. If you only see +a partial display - this may be the option for you. Default: on. +.TP +.BI "Option \*qCyberStretch\*q \*q" boolean \*q +For Cyber chipsets only, turn on stretching. When the resolution is lower +than the LCD's screen, this option will stretch the graphics mode to +fill the entire LCD. Default: off. +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. Default: off. +.TP +.BI "Option \*qVideoKey\*q \*q" integer \*q +This sets the default pixel value for the YUV video overlay key. +Default: undefined. +.TP +.BI "Option \*qNoPciBurst\*q \*q" boolean \*q +Turn off PCI burst mode, PCI Bursting is on by default. +Default: off. +.TP +.BI "Option \*qXvHsync\*q \*q" integer \*q +Override the default Horizontal-sync value for the Xv extension. +This is used to center the Xv image on the screen. By default the values +are assigned based on the video card. +Default: 0. +.TP +.BI "Option \*qXvVsync\*q \*q" integer \*q +Override the default Vertical-sync value for the Xv extension. +This is used to center the Xv image on the screen. By default the values +are assigned based on the video card. +Default: 0. +.TP +.BI "Option \*qXvBskew\*q \*q" integer \*q +Override the default Bottom skew value for the Xv extension. +This is used to extend the Xv image on the screen at the bottom. By +default the values are assigned based on the video card. +Default: 0. +.TP +.BI "Option \*qXvRskew\*q \*q" integer \*q +Override the default Right skew value for the Xv extension. +This is used to extend the Xv image on the screen at the right. By +default the values are assigned based on the video card. +Default: 0. +.TP +.BI "Option \*qDisplay\*q \*q" string \*q +Override the display. +Possible values are \*qCRT\*q, \*qLCD\*q and \*qDual\*q. +Please note that this option is only experimentally. +Default: Use display active when X started. +.TP +.BI "Option \*qDisplay1400\*q \*q" boolean \*q +Inform driver to expect 1400x1050 display instead of a 1280x1024. +Default: off. +.TP +.BI "Option \*qGammaBrightness\*q \*q" string \*q +Set display gamma value and brightness. \*q\fIstring\fP\*q is +\*q\fIgamma\fP, \fIbrightness\fP\*q, where \fIgamma\fP is a floating +point value greater than 0 and less or equal to 10. \fIbrightness\fP is +an integer value greater or equal to 0 and less than 128. +Default: gamma and brightness control is turned off. +Note: This is not supported on all chipsets. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.SH AUTHOR +Author: Alan Hourihane diff --git a/src/blade_accel.c b/src/blade_accel.c new file mode 100644 index 0000000..e76860d --- /dev/null +++ b/src/blade_accel.c @@ -0,0 +1,704 @@ +/* + * Copyright 1997,1998 by Alan Hourihane, Wigan, England. + * + * 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * Trident Blade3D accelerated options. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/blade_accel.c,v 1.18 2002/10/08 22:14:11 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "miline.h" + +#include "trident.h" +#include "trident_regs.h" + +#include "xaarop.h" +#include "xaalocal.h" + +static void BladeSync(ScrnInfoPtr pScrn); +#if 0 +static void BladeSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void BladeSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant); +static void BladeSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags); +static void BladeSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int length, + unsigned char *pattern); +static void BladeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags, + int phase); +#endif +static void BladeSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void BladeSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, + int y, int w, int h); +static void BladeSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, + int y2, int w, int h); +static void BladeSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int transparency_color); +#if 0 +static void BladeSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void BladeSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int srcx, int srcy, + int offset); +#endif +static void BladeSetupForCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void BladeSubsequentCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft); +static void BladeSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2); +static void BladeDisableClipping(ScrnInfoPtr pScrn); +static void BladeSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, int fg, int bg, + int rop, unsigned int planemask); +static void BladeSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#if 0 +static void BladeSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, unsigned int planemask, int trans_col); +static void BladeSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#endif +static void BladeSetupForImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); +static void BladeSubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft); + +static void +BladeInitializeAccelerator(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD32 stride; + + stride = (pScrn->displayWidth >> 3) << 20; + + BLADE_OUT(0x21C8, stride); + BLADE_OUT(0x21CC, stride); + BLADE_OUT(0x21D0, stride); + BLADE_OUT(0x21D4, stride); + switch (pScrn->depth) { + case 8: + stride |= 0<<29; + break; + case 15: + stride |= 5<<29; + break; + case 16: + stride |= 1<<29; + break; + case 24: + stride |= 2<<29; + break; + } + BLADE_OUT(0x21B8, 0); + BLADE_OUT(0x21B8, stride); + BLADE_OUT(0x21BC, stride); + BLADE_OUT(0x21C0, stride); + BLADE_OUT(0x21C4, stride); +#if 0 + /* It appears that the driver sometimes misdetects the RAM type, so we + * don't force this for now */ + if (pTrident->HasSGRAM) + BLADE_OUT(0x2168, 1<<26); /* Enables Block Write if available (SGRAM) */ + else + BLADE_OUT(0x2168, 0); +#endif + BLADE_OUT(0x216C, 0); +} + +Bool +BladeAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + BoxRec AvailFBArea; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (pTrident->FbMapSize - 4096) / (pScrn->displayWidth * + pScrn->bitsPerPixel / 8); + if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047; + + xf86InitFBManager(pScreen, &AvailFBArea); + + if (pTrident->NoAccel) + return FALSE; + + pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + pTrident->InitializeAccelerator = BladeInitializeAccelerator; + BladeInitializeAccelerator(pScrn); + + infoPtr->Flags = PIXMAP_CACHE | + LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS; + + infoPtr->Sync = BladeSync; + + infoPtr->SetClippingRectangle = BladeSetClippingRectangle; + infoPtr->DisableClipping = BladeDisableClipping; + +#if 0 + infoPtr->SolidLineFlags = 0; + infoPtr->SetupForSolidLine = BladeSetupForSolidLine; + infoPtr->SubsequentSolidTwoPointLine = BladeSubsequentSolidTwoPointLine; + infoPtr->SetupForDashedLine = BladeSetupForDashedLine; + infoPtr->SubsequentDashedTwoPointLine = BladeSubsequentDashedTwoPointLine; + infoPtr->DashPatternMaxLength = 16; + infoPtr->DashedLineFlags = LINE_PATTERN_LSBFIRST_LSBJUSTIFIED | + LINE_PATTERN_POWER_OF_2_ONLY; +#endif + + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = BladeSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = BladeSubsequentFillRectSolid; + + infoPtr->ScreenToScreenCopyFlags = ONLY_TWO_BITBLT_DIRECTIONS | + NO_PLANEMASK | + NO_TRANSPARENCY; + + infoPtr->SetupForScreenToScreenCopy = + BladeSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + BladeSubsequentScreenToScreenCopy; + + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | NO_TRANSPARENCY | + BIT_ORDER_IN_BYTE_MSBFIRST | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS; + + infoPtr->SetupForMono8x8PatternFill = + BladeSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + BladeSubsequentMono8x8PatternFillRect; + +#if 0 + infoPtr->Color8x8PatternFillFlags = + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + + infoPtr->SetupForColor8x8PatternFill = + TridentSetupForColor8x8PatternFill; + infoPtr->SubsequentColor8x8PatternFillRect = + TridentSubsequentColor8x8PatternFillRect; + + infoPtr->ScreenToScreenColorExpandFillFlags = 0; + + infoPtr->SetupForScreenToScreenColorExpandFill = + BladeSetupForScreenToScreenColorExpand; + infoPtr->SubsequentScreenToScreenColorExpandFill = + BladeSubsequentScreenToScreenColorExpand; +#endif + + infoPtr->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD | + LEFT_EDGE_CLIPPING | + SYNC_AFTER_COLOR_EXPAND | + NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST | + SCANLINE_PAD_DWORD; + infoPtr->ColorExpandRange = 0x10000; + infoPtr->ColorExpandBase = pTrident->IOBase + 0x10000; + infoPtr->SetupForCPUToScreenColorExpandFill = + BladeSetupForCPUToScreenColorExpand; + infoPtr->SubsequentCPUToScreenColorExpandFill = + BladeSubsequentCPUToScreenColorExpand; + + infoPtr->SetupForImageWrite = BladeSetupForImageWrite; + infoPtr->SubsequentImageWriteRect = + BladeSubsequentImageWriteRect; + infoPtr->ImageWriteFlags = NO_PLANEMASK | + LEFT_EDGE_CLIPPING | + CPU_TRANSFER_PAD_DWORD | + SYNC_AFTER_IMAGE_WRITE; + infoPtr->ImageWriteBase = pTrident->IOBase + 0x10000; + infoPtr->ImageWriteRange = 0x10000; + + return(XAAInit(pScreen, infoPtr)); +} + +static void +BladeSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int busy; + int cnt = 10000000; + + if (pTrident->Clipping) BladeDisableClipping(pScrn); + BLADE_OUT(0x216C, 0); + + BLADEBUSY(busy); + while (busy != 0) { + if (--cnt < 0) { + ErrorF("GE timeout\n"); + BLADE_OUT(0x2124, 1<<7); + BLADE_OUT(0x2124, 0); + break; + } + BLADEBUSY(busy); + } +} + +static void +BladeSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->BltScanDirection = 0; + if ((xdir < 0) || (ydir < 0)) pTrident->BltScanDirection |= 1<<1; + +#if 0 + if (transparency_color != -1) { + BLADE_OUT(0x2168, transparency_color & 0xffffff); + pTrident->BltScanDirection |= 1<<6; + } +#endif + + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } + BLADE_OUT(0x2148, XAACopyROP[rop]); +} + +static void +BladeSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int clip = 0; + + if (pTrident->Clipping) clip = 1; + + BLADE_OUT(0x2144, 0xE0000000 | 1<<19 | 1<<4 | 1<<2 | pTrident->BltScanDirection | clip); + + if (pTrident->BltScanDirection) { + BLADE_OUT(0x2100, (y1+h-1)<<16 | (x1+w-1)); + BLADE_OUT(0x2104, y1<<16 | x1); + BLADE_OUT(0x2108, (y2+h-1)<<16 | (x2+w-1)); + BLADE_OUT(0x210C, (y2&0xfff)<<16 | (x2&0xfff)); + } else { + BLADE_OUT(0x2100, y1<<16 | x1); + BLADE_OUT(0x2104, (y1+h-1)<<16 | (x1+w-1)); + BLADE_OUT(0x2108, y2<<16 | x2); + BLADE_OUT(0x210C, ((y2+h-1)&0xfff)<<16 | ((x2+w-1)&0xfff)); + } +} + +static void +BladeSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + BLADE_OUT(0x2154, (y1&0x0fff)<<16 | (x1&0x0fff)); + BLADE_OUT(0x2158, (y2&0x0fff)<<16 | (x2&0x0fff)); + pTrident->Clipping = TRUE; +} + +static void +BladeDisableClipping(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + pTrident->Clipping = FALSE; +} + +#if 0 +static void +BladeSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + REPLICATE(color); + BLADE_OUT(0x2160, color); + BLADE_OUT(0x2148, XAACopyROP[rop]); + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp; + int D = 0, E = 0, ymajor = 0; + + + BLADE_OUT(0x2144, 0x20000000 | 3<<19 | 1<<4 | 2<<2 | (pTrident->Clipping ? 1: 0)); + + if (!(octant & YMAJOR)) { + if ((!(octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 1; D = 0;} + if ((!(octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 1; D = 1;} + if (( (octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 1; D = 2;} + if (( (octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 1; D = 3;} + ymajor = 0; + } else { + if ((!(octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 0; D = 0;} + if ((!(octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 0; D = 2;} + if (( (octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 0; D = 1;} + if (( (octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 0; D = 3;} + ymajor = 1<<21; + } + + if (E) { + tmp = x; x = y; y = tmp; + } + BLADE_OUT(0x2130, 0x00000001); + if (D&0x02) { + BLADE_OUT(0x213C, 0x10000000 | 1<<25 | 1<<19 | 1<<17 | ymajor | ((x+len-1)<<4)); + } else { + BLADE_OUT(0x213C, 0x10000000 | 1<<25 | 1<<19 | 1<<17 | ymajor | ((y+len-1)<<4)); + } + BLADE_OUT(0x2140, E<<30 | (y&0xfff)<<20 | ((x&0xfff)<<4)); + BLADE_OUT(0x2144, D<<30 | (((dmaj-dmin)&0xfff) << 16) | (-dmin&0xfff)); + BLADE_OUT(0x2148, ((-(dmin+e)&0xfff) << 16)); +} + +static void +BladeSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + +#if 0 + if (flags & OMIT_LAST) + BladeSetClippingRectangle(pScrn,x1,y1,x2-1,y2-1); +#endif + + BLADE_OUT(0x2144, 0x20000000 | pTrident->BltScanDirection | 1<<19 | 1<<4 | 2<<2); + BLADE_OUT(0x2130, 0x3); + BLADE_OUT(0x2108, y1<<16 | x1); + BLADE_OUT(0x210C, (y2&0xfff)<<16 | (x2&0xfff)); + +#if 0 + if (flags & OMIT_LAST) + BladeDisableClipping(pScrn); +#endif +} + +static void +BladeSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, unsigned char *pattern) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->LinePattern = *((CARD16 *)pattern) & ((1<<length) - 1); + switch (length) { + case 2: + pTrident->LinePattern = pTrident->LinePattern | (pTrident->LinePattern << 2); + case 4: + pTrident->LinePattern = pTrident->LinePattern | (pTrident->LinePattern << 4); + case 8: + pTrident->LinePattern = pTrident->LinePattern | (pTrident->LinePattern << 8); + } + + REPLICATE(fg); + REPLICATE(bg); + BLADE_OUT(0x2160, fg); + BLADE_OUT(0x2164, bg); + BLADE_OUT(0x2148, XAACopyROP[rop]); + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags, int phase) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (flags & OMIT_LAST) + BladeSetClippingRectangle(pScrn,x1,y1,x2-1,y2-1); + + BLADE_OUT(0x216C, (pTrident->LinePattern >> phase) | (pTrident->LinePattern << (16-phase))); + BLADE_OUT(0x2144, 0x20000000 | pTrident->BltScanDirection | 1<<27 | 1<<19 | 1<<4 | 2<<2); + BLADE_OUT(0x2108, y1<<16 | x1); + BLADE_OUT(0x210C, (y2&0xfff)<<16 | (x2&0xfff)); + + if (flags & OMIT_LAST) + BladeDisableClipping(pScrn); +} +#endif + +static void +BladeSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + REPLICATE(color); + BLADE_OUT(0x2160, color); + BLADE_OUT(0x2148, XAACopyROP[rop]); + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + BLADE_OUT(0x2144, 0x20000000 | pTrident->BltScanDirection | 1<<19 | 1<<4 | 2<<2 | (pTrident->Clipping ? 1:0)); + BLADE_OUT(0x2108, y<<16 | x); + BLADE_OUT(0x210C, ((y+h-1)&0xfff)<<16 | ((x+w-1)&0xfff)); +} + +#if 0 +static void +BladeSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->ROP = rop; + + REPLICATE(bg); + REPLICATE(fg); + IMAGE_OUT(0x44, fg); + IMAGE_OUT(0x48, bg); + IMAGE_OUT(0x20, 0x90000000 | XAACopyROP[rop]); + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int srcx, int srcy, int offset) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x00, srcy<<16 | srcx); + IMAGE_OUT(0x04, (srcy+h-1)<<16 | (srcx+w-1)); + IMAGE_OUT(0x08, y<<16 | x); + IMAGE_OUT(0x0C, (y+h-1)<<16 | (x+w-1)); + + IMAGE_OUT(0x24, 0x80000000 | 3<<22 | 1<<7 | pTrident->BltScanDirection | (pTrident->ROP == GXcopy ? 0 : 1<<10) | offset<<25); +} +#endif + +static void +BladeSetupForCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->BltScanDirection = 0; + BLADE_OUT(0x2148, XAACopyROP[rop]); + if (bg == -1) { + pTrident->BltScanDirection |= 2<<19; + REPLICATE(fg); + BLADE_OUT(0x2160, fg); + BLADE_OUT(0x2164, ~fg); + } else { + pTrident->BltScanDirection |= 3<<19; + REPLICATE(fg); + REPLICATE(bg); + BLADE_OUT(0x2160, fg); + BLADE_OUT(0x2164, bg); + } + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (skipleft) BladeSetClippingRectangle(pScrn,x+skipleft,y,(x+w-1),(y+h-1)); + BLADE_OUT(0x2144, 0xE0000000 | pTrident->BltScanDirection | 1<<4 | (skipleft ? 1 : 0)); + BLADE_OUT(0x2108, (y&0xfff)<<16 | (x&0xfff)); + BLADE_OUT(0x210C, ((y+h-1)&0xfff)<<16 | ((x+w-1)&0xfff)); +} + +static void +BladeSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + BladeSync(pScrn); + BLADE_OUT(0x2148, XAAPatternROP[rop]); + + if (bg == -1) { + REPLICATE(fg); + BLADE_OUT(0x216C, 0x80000000 | 1<<30); + BLADE_OUT(0x216C, 0x80000000 | 1<<28 | 1<<30); + BLADE_OUT(0x2170, patternx); + BLADE_OUT(0x2170, patterny); + BLADE_OUT(0x2174, fg); +#if 0 + BLADE_OUT(0x2178, ~fg); +#endif + } else { + REPLICATE(fg); + REPLICATE(bg); + BLADE_OUT(0x216C, 0x80000000); + BLADE_OUT(0x216C, 0x80000000 | 1<<28); + BLADE_OUT(0x2170, patternx); + BLADE_OUT(0x2170, patterny); + BLADE_OUT(0x2174, fg); + BLADE_OUT(0x2178, bg); + } + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int clip = 0; + + if (pTrident->Clipping) clip = 1; + BLADE_OUT(0x2144, 0x20000000 | pTrident->BltScanDirection | 7<<12 | 1<<4 | 1<<19 | 2<<2 | clip); + BLADE_OUT(0x2108, y<<16 | x); + BLADE_OUT(0x210C, ((y+h-1)&0xfff)<<16 | ((x+w-1)&0xfff)); +} + +#if 0 +static void +BladeSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, + unsigned int planemask, + int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_PATLOC(((patterny * pScrn->displayWidth * pScrn->bitsPerPixel / 8) + + (patternx * pScrn->bitsPerPixel / 8)) >> 6); + pTrident->BltScanDirection = 0; + if (transparency_color != -1) { + BLADE_OUT(0x2168, transparency_color & 0xffffff); + pTrident->BltScanDirection |= 1<<6; + } + TGUI_FMIX(XAAPatternROP[rop]); + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void +BladeSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DEST_XY(x,y); + TGUI_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + CHECKCLIPPING; +} +#endif + +static void BladeSetupForImageWrite( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + BLADE_OUT(0x2148, XAACopyROP[rop]); + pTrident->BltScanDirection = 0; + REPLICATE(planemask); + if (planemask != -1) { + BLADE_OUT(0x2184, ~planemask); + pTrident->BltScanDirection |= 1<<5; + } +} + +static void BladeSubsequentImageWriteRect( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (skipleft) BladeSetClippingRectangle(pScrn,x+skipleft,y,(x+w-1),(y+h-1)); + BLADE_OUT(0x2144, 0xE0000000 | 1<<19 | 1<<4 | pTrident->BltScanDirection | (skipleft ? 1 : 0)); + BLADE_OUT(0x2108, y<<16 | (x&0xfff)); + BLADE_OUT(0x210C, ((y+h-1)&0xfff)<<16 | ((x+w-1)&0xfff)); +} diff --git a/src/image_accel.c b/src/image_accel.c new file mode 100644 index 0000000..485f455 --- /dev/null +++ b/src/image_accel.c @@ -0,0 +1,647 @@ +/* + * Copyright 1997,1998 by Alan Hourihane, Wigan, England. + * + * 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * Trident 3DImage' accelerated options. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/image_accel.c,v 1.24 2001/10/28 03:33:51 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "miline.h" + +#include "trident.h" +#include "trident_regs.h" + +#include "xaarop.h" +#include "xaalocal.h" + +static void ImageSync(ScrnInfoPtr pScrn); +static void ImageSyncClip(ScrnInfoPtr pScrn); +#if 0 +static void ImageSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void ImageSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant); +#endif +static void ImageSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void ImageSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, + int y, int w, int h); +static void ImageSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, + int y2, int w, int h); +static void ImageSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int transparency_color); +static void ImageSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2); +static void ImageDisableClipping(ScrnInfoPtr pScrn); +static void ImageSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, int fg, int bg, + int rop, unsigned int planemask); +static void ImageSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#if 0 +static void ImageSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, unsigned int planemask, int trans_col); +static void ImageSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#endif +static void ImageSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); +static void ImageSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft); +static void ImageSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno); +static void ImageSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void ImageSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft); +static void ImageSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); + +static void +ImageInitializeAccelerator(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + switch (pScrn->depth) { + case 8: + pTrident->EngineOperation = 0; + break; + case 15: + pTrident->EngineOperation = 5; + break; + case 16: + pTrident->EngineOperation = 1; + break; + case 24: + pTrident->EngineOperation = 2; + break; + } + IMAGE_OUT(0x2120, 0xF0000000); + IMAGE_OUT(0x2120, 0x40000000 | pTrident->EngineOperation); + IMAGE_OUT(0x2120, 0x80000000); + IMAGE_OUT(0x2144, 0x00000000); + IMAGE_OUT(0x2148, 0x00000000); + IMAGE_OUT(0x2150, 0x00000000); + IMAGE_OUT(0x2154, 0x00000000); + IMAGE_OUT(0x2120, 0x60000000 |pScrn->displayWidth<<16 |pScrn->displayWidth); + IMAGE_OUT(0x216C, 0x00000000); + IMAGE_OUT(0x2170, 0x00000000); + IMAGE_OUT(0x217C, 0x00000000); + IMAGE_OUT(0x2120, 0x10000000); + IMAGE_OUT(0x2130, 2047 << 16 | 2047); + pTrident->Clipping = FALSE; + pTrident->DstEnable = FALSE; +} + +Bool +ImageAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + BoxRec AvailFBArea; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (pTrident->FbMapSize - 4096) / (pScrn->displayWidth * + pScrn->bitsPerPixel / 8); + if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047; + + xf86InitFBManager(pScreen, &AvailFBArea); + + if (pTrident->NoAccel) + return FALSE; + + pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + pTrident->InitializeAccelerator = ImageInitializeAccelerator; + ImageInitializeAccelerator(pScrn); + + infoPtr->Flags = PIXMAP_CACHE | + LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS; + + infoPtr->Sync = ImageSync; + +#if 0 + infoPtr->SetClippingRectangle = ImageSetClippingRectangle; + infoPtr->DisableClipping = ImageDisableClipping; + infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_FILL | + HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | + HARDWARE_CLIP_MONO_8x8_FILL; +#endif + +#if 0 + infoPtr->SolidLineFlags = NO_PLANEMASK; + infoPtr->SetupForSolidLine = ImageSetupForSolidLine; + infoPtr->SolidBresenhamLineErrorTermBits = 13; + infoPtr->SubsequentSolidBresenhamLine = ImageSubsequentSolidBresenhamLine; + infoPtr->ClippingFlags |= HARDWARE_CLIP_SOLID_LINE; +#endif + + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = ImageSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = ImageSubsequentFillRectSolid; + + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | + NO_TRANSPARENCY | + ONLY_TWO_BITBLT_DIRECTIONS; + + infoPtr->SetupForScreenToScreenCopy = + ImageSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + ImageSubsequentScreenToScreenCopy; + + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS; + + infoPtr->SetupForMono8x8PatternFill = + ImageSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + ImageSubsequentMono8x8PatternFillRect; + +#if 0 + infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | + NO_TRANSPARENCY | + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + + infoPtr->SetupForColor8x8PatternFill = + ImageSetupForColor8x8PatternFill; + infoPtr->SubsequentColor8x8PatternFillRect = + ImageSubsequentColor8x8PatternFillRect; + infoPtr->ClippingFlags |= HARDWARE_CLIP_COLOR_8x8_FILL; +#endif + + if (pTrident->Chipset != CYBER9397DVD) { + /* It seems as though the 9397DVD doesn't like the transfer window */ + /* But then, I've also tried at the two port addresses too, with */ + /* no luck. Disable for this chipset for now. I'd guess there's some */ + /* extra setup needed for this chipset. */ + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | + LEFT_EDGE_CLIPPING | + BIT_ORDER_IN_BYTE_MSBFIRST; + + pTrident->XAAScanlineColorExpandBuffers[0] = + xnfalloc(((pScrn->virtualX + 63)) *4* (pScrn->bitsPerPixel / 8)); + + infoPtr->NumScanlineColorExpandBuffers = 1; + infoPtr->ScanlineColorExpandBuffers = + pTrident->XAAScanlineColorExpandBuffers; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + ImageSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + ImageSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = + ImageSubsequentColorExpandScanline; + + infoPtr->ScanlineImageWriteFlags = NO_PLANEMASK | + LEFT_EDGE_CLIPPING; + + infoPtr->SetupForScanlineImageWrite = ImageSetupForScanlineImageWrite; + infoPtr->SubsequentScanlineImageWriteRect = + ImageSubsequentScanlineImageWriteRect; + infoPtr->SubsequentImageWriteScanline = ImageSubsequentImageWriteScanline; + + infoPtr->NumScanlineImageWriteBuffers = 1; + infoPtr->ScanlineImageWriteBuffers = pTrident->XAAImageScanlineBuffer; + + pTrident->XAAImageScanlineBuffer[0] = + xnfalloc(pScrn->virtualX * pScrn->bitsPerPixel / 8); + + infoPtr->ImageWriteBase = pTrident->IOBase + 0x10000; + } + + return(XAAInit(pScreen, infoPtr)); +} + +static void +ImageSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int busy; + int cnt = 5000000; + + if (pTrident->Clipping) ImageDisableClipping(pScrn); + if (pTrident->DstEnable) { + IMAGE_OUT(0x2120, 0x70000000); + pTrident->DstEnable = FALSE; + } + + IMAGEBUSY(busy); + while (busy != 0) { + if (--cnt < 0) { + ErrorF("GE timeout\n"); + IMAGE_OUT(0x2164, 0x80000000); + } + IMAGEBUSY(busy); + } +} + +static void +ImageSyncClip(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int busy; + int cnt = 5000000; + + IMAGEBUSY(busy); + while (busy != 0) { + if (--cnt < 0) { + ErrorF("GE timeout\n"); + IMAGE_OUT(0x2164, 0x80000000); + } + IMAGEBUSY(busy); + } +} + +static void +ImageSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->BltScanDirection = 0; + if ((xdir < 0) || (ydir < 0)) pTrident->BltScanDirection |= 1<<2; + + IMAGE_OUT(0x2120, 0x80000000); + IMAGE_OUT(0x2120, 0x90000000 | XAACopyROP[rop]); + + if (transparency_color != -1) { + IMAGE_OUT(0x2120, 0x70000000 | 1<<26 | (transparency_color&0xffffff)); + pTrident->DstEnable = TRUE; + } +} + +static void +ImageSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (pTrident->BltScanDirection) { + IMAGE_OUT(0x2100, (y1+h-1)<<16 | (x1+w-1)); + IMAGE_OUT(0x2104, y1<<16 | x1); + IMAGE_OUT(0x2108, (y2+h-1)<<16 | (x2+w-1)); + IMAGE_OUT(0x210C, y2<<16 | x2); + } else { + IMAGE_OUT(0x2100, y1<<16 | x1); + IMAGE_OUT(0x2104, (y1+h-1)<<16 | (x1+w-1)); + IMAGE_OUT(0x2108, y2<<16 | x2); + IMAGE_OUT(0x210C, (y2+h-1)<<16 | (x2+w-1)); + } + + IMAGE_OUT(0x2124, 0x80000000 | 1<<7 | 1<<22 | 1<<10 | pTrident->BltScanDirection | (pTrident->Clipping ? 1 : 0)); + + if (!pTrident->UsePCIRetry) + ImageSyncClip(pScrn); +} + +static void +ImageSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2120, 0x10000000 | ((y1&0xfff)<<16) | (x1&0xfff)); + IMAGE_OUT(0x2130, ((y2&0xfff)<<16) | (x2&0xfff)); + pTrident->Clipping = TRUE; +} + +static void +ImageDisableClipping(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + pTrident->Clipping = FALSE; +} + +#if 0 +static void +ImageSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + REPLICATE(color); + IMAGE_OUT(0x2120, 0x84000000); + IMAGE_OUT(0x2120, 0x90000000 | XAACopyROP[rop]); + IMAGE_OUT(0x2144, color); +} + +static void +ImageSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp; + int D = 0, E = 0, ymajor = 0; + + IMAGE_OUT(0x2124, 0x20000000 | 3<<22 | 1<<10 | 1<<9 | (pTrident->Clipping ? 1:0)); + if (!(octant & YMAJOR)) { + if ((!(octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 1; D = 0;} + if ((!(octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 1; D = 1;} + if (( (octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 1; D = 2;} + if (( (octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 1; D = 3;} + ymajor = 0; + } else { + if ((!(octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 0; D = 0;} + if ((!(octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 0; D = 2;} + if (( (octant&XDECREASING)) && (!(octant&YDECREASING))) {E = 0; D = 1;} + if (( (octant&XDECREASING)) && ( (octant&YDECREASING))) {E = 0; D = 3;} + ymajor = 1<<18; + } + + if (E) { + tmp = x; x = y; y = tmp; + } + if (D&0x02) { + IMAGE_OUT(0x21FC, 0x20000000 | 1<<27 | 1<<19 | 1<<17 | ymajor | (x+len-1)); + } else { + IMAGE_OUT(0x21FC, 0x20000000 | 1<<27 | 1<<19 | 1<<17 | ymajor | (y+len-1)); + } + IMAGE_OUT(0x2100, E<<30 | (y&0xfff)<<16 | (x&0xfff)); + IMAGE_OUT(0x2104, D<<30 | (((dmaj-dmin)&0xfff) << 16) | (-dmin&0xfff)); + IMAGE_OUT(0x2108, ((-e&0xfff) << 16)); + + if (!pTrident->UsePCIRetry) + ImageSyncClip(pScrn); +} +#endif + +static void +ImageSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + REPLICATE(color); + IMAGE_OUT(0x2120, 0x80000000); + IMAGE_OUT(0x2120, 0x90000000 | XAACopyROP[rop]); + IMAGE_OUT(0x2144, color); +} + +static void +ImageSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if ((w<=0) || (h<=0)) + return; + + IMAGE_OUT(0x2108, ((y&0xfff)<<16) | (x&0xfff)); + IMAGE_OUT(0x210C, (((y+h-1)&0xfff)<<16) | ((x+w-1)&0xfff)); + IMAGE_OUT(0x2124, 0x80000000| 3<<22| 1<<10| 1<<9| (pTrident->Clipping?1:0)); + if (!pTrident->UsePCIRetry) + ImageSyncClip(pScrn); +} + +static +void MoveDWORDS( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + Bool extra = FALSE; + if (dwords & 0x01) extra = TRUE; + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + if(!dwords) { + if (extra) *dest = 0x00000000; + return; + } + *dest = *src; + if(dwords == 1) { + if (extra) *(dest + 1) = 0x00000000; + return; + } + *(dest + 1) = *(src + 1); + if(dwords == 2) { + if (extra) *(dest + 2) = 0x00000000; + return; + } + *(dest + 2) = *(src + 2); + if (extra) *(dest + 3) = 0x00000000; +} + +static void +ImageSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2120, 0x90000000 | XAAPatternROP[rop]); + if (bg == -1) { + REPLICATE(fg); + IMAGE_OUT(0x2120, 0x80000000 | 1<<27); + IMAGE_OUT(0x2130, patternx); + IMAGE_OUT(0x2134, patterny); + IMAGE_OUT(0x2150, fg); + IMAGE_OUT(0x2154, ~fg); + } else { + REPLICATE(bg); + REPLICATE(fg); + IMAGE_OUT(0x2120, 0x80000000 | 1<<27 | 1<<26); + IMAGE_OUT(0x2130, patternx); + IMAGE_OUT(0x2134, patterny); + IMAGE_OUT(0x2150, fg); + IMAGE_OUT(0x2154, bg); + } +} + +static void +ImageSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2108, ((y&0xfff)<<16) | (x&0xfff)); + IMAGE_OUT(0x210C, (((y+h-1)&0xfff)<<16) | ((x+w-1)&0xfff)); + IMAGE_OUT(0x2124, 0x80000000 | 7<<18 | 1<<22 | 1<<10 | 1<<9 | (pTrident->Clipping ? 1 : 0)); + if (!pTrident->UsePCIRetry) + ImageSyncClip(pScrn); +} + +#if 0 +static void +ImageSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, + unsigned int planemask, + int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2120, 0x90000000 | XAAPatternROP[rop]); + IMAGE_OUT(0x2120, 0x80000000 | 1<<26); + if (transparency_color != -1) { + IMAGE_OUT(0x2120, 0x70000000 | 1<<26 | (transparency_color&0xffffff)); + pTrident->DstEnable = TRUE; + } +} + +static void +ImageSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2100, (patterny&0xfff)<<16 | (patternx&0xfff)); + IMAGE_OUT(0x2104, (((patterny+h-1)&0xfff)<<16) | ((patternx+w-1)&0xfff)); + IMAGE_OUT(0x2108, (y&0xfff)<<16 | (x&0xfff)); + IMAGE_OUT(0x210C, (((y+h-1)&0xfff)<<16) | ((x+w-1)&0xfff)); + IMAGE_OUT(0x2124, 0x80000000 | 1<<22 | 1<<10 | 1<<7 | (pTrident->Clipping ? 1 : 0)); + if (!pTrident->UsePCIRetry) + ImageSyncClip(pScrn); +} +#endif + +static void +ImageSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + IMAGE_OUT(0x2120, 0x80000000); + IMAGE_OUT(0x2120, 0x90000000 | XAACopyROP[rop]); + if (bg == -1) { + pTrident->ROP = 2<<22; + REPLICATE(fg); + IMAGE_OUT(0x2144, fg); + IMAGE_OUT(0x2148, ~fg); + } else { + pTrident->ROP = 3<<22; + REPLICATE(fg); + IMAGE_OUT(0x2144, fg); + REPLICATE(bg); + IMAGE_OUT(0x2148, bg); + } +} + +static void +ImageSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + ImageSetClippingRectangle(pScrn,(x+skipleft),y,(x+w-1),(y+h-1)); + IMAGE_OUT(0x2108, (y&0xfff)<<16 | (x&0xfff)); + IMAGE_OUT(0x210C, (((y+h-1)&0xfff)<<16) | ((x+w-1)&0xfff)); + IMAGE_OUT(0x2124, 0x80000000 | pTrident->ROP | 1<<10 | 1); + pTrident->dwords = (w + 31) >> 5; + pTrident->h = h; +} + +static void +ImageSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XAAInfoRecPtr infoRec; + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + MoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)pTrident->XAAScanlineColorExpandBuffers[bufno], pTrident->dwords); + + pTrident->h--; + if (!pTrident->h) + ImageSync(pScrn); +} + +static void +ImageSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + IMAGE_OUT(0x2120, 0x90000000 | XAACopyROP[rop]); + if (transparency_color != -1) { + IMAGE_OUT(0x2120, 0x70000000 | 1<<26 | (transparency_color&0xffffff)); + pTrident->DstEnable = TRUE; + } + IMAGE_OUT(0x2120, 0x80000000); +} + +static void +ImageSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y, + int w, int h, int skipleft) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + ImageSetClippingRectangle(pScrn,(x+skipleft),y,(x+w-1),(y+h-1)); + IMAGE_OUT(0x2108, ((y&0xfff)<<16) | (x&0xfff)); + IMAGE_OUT(0x210C, (((y+h-1)&0xfff)<<16) | ((x+w-1)&0xfff)); + IMAGE_OUT(0x2124, 0x80000000 | 1<<22 | 1<<10 | 1); + pTrident->dwords = ((w * (pScrn->bitsPerPixel/8)) + 3) >> 2; + pTrident->h = h; +} + + +static void +ImageSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XAAInfoRecPtr infoRec; + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + MoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)pTrident->XAAImageScanlineBuffer[bufno], pTrident->dwords); + + pTrident->h--; + if (!pTrident->h) + ImageSync(pScrn); +} diff --git a/src/trident.h b/src/trident.h new file mode 100644 index 0000000..a73ae53 --- /dev/null +++ b/src/trident.h @@ -0,0 +1,346 @@ +/* + * Copyright 1992-2000 by Alan Hourihane <alanh@fairlite.demon.co.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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident.h,v 1.56 2002/09/16 18:06:02 eich Exp $ */ +/*#define VBE_INFO*/ + +#ifndef _TRIDENT_H_ +#define _TRIDENT_H_ + +#include "xf86Cursor.h" +#include "xaa.h" +#include "xf86RamDac.h" +#include "compiler.h" +#include "vgaHW.h" +#include "xf86i2c.h" +#include "xf86int10.h" +#include "shadowfb.h" +#include "shadow.h" +#include "xf86xv.h" +#include "xf86Pci.h" +#include "vbe.h" + +typedef struct { + unsigned char tridentRegs3x4[0x100]; + unsigned char tridentRegs3CE[0x100]; + unsigned char tridentRegs3C4[0x100]; + unsigned char tridentRegsDAC[0x01]; + unsigned char tridentRegsClock[0x03]; + unsigned char DacRegs[0x300]; +} TRIDENTRegRec, *TRIDENTRegPtr; + +#define TRIDENTPTR(p) ((TRIDENTPtr)((p)->driverPrivate)) + +typedef struct { + ScrnInfoPtr pScrn; + pciVideoPtr PciInfo; + PCITAG PciTag; + EntityInfoPtr pEnt; + int Chipset; + int DACtype; + int RamDac; + int ChipRev; + int HwBpp; + int BppShift; + CARD32 IOAddress; + unsigned long FbAddress; + unsigned char * IOBase; + unsigned char * FbBase; + long FbMapSize; + IOADDRESS PIOBase; + Bool NoAccel; + Bool HWCursor; + Bool UsePCIRetry; + Bool UsePCIBurst; + Bool NewClockCode; + Bool Clipping; + Bool DstEnable; + Bool ROP; + Bool HasSGRAM; + Bool MUX; + Bool IsCyber; + Bool CyberShadow; + Bool CyberStretch; + Bool NoMMIO; + Bool MMIOonly; + Bool ShadowFB; + Bool Linear; + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + unsigned char * ShadowPtr; + int ShadowPitch; + RefreshAreaFuncPtr RefreshArea; + void (*PointerMoved)(int index, int x, int y); + int Rotate; + float frequency; + unsigned char REGPCIReg; + unsigned char REGNewMode1; + CARD8 SaveClock1; + CARD8 SaveClock2; + CARD8 SaveClock3; + int MinClock; + int MaxClock; + int MUXThreshold; + int currentClock; + int MCLK; + int dwords; + int h; + int x; + int w; + int y; + int lcdMode; + Bool lcdActive; + Bool doInit; +#ifdef READOUT + Bool DontSetClock; +#endif + TRIDENTRegRec SavedReg; + TRIDENTRegRec ModeReg; + I2CBusPtr DDC; + CARD16 EngineOperation; + CARD32 PatternLocation; + CARD32 BltScanDirection; + CARD32 DrawFlag; + CARD16 LinePattern; + RamDacRecPtr RamDacRec; + xf86CursorInfoPtr CursorInfoRec; + xf86Int10InfoPtr Int10; + vbeInfoPtr pVbe; +#ifdef VBE_INFO + vbeModeInfoPtr vbeModes; +#endif + XAAInfoRecPtr AccelInfoRec; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; + int panelWidth; + int panelHeight; + unsigned int (*ddc1Read)(ScrnInfoPtr); + CARD8* XAAScanlineColorExpandBuffers[2]; + CARD8* XAAImageScanlineBuffer[1]; + void (*InitializeAccelerator)(ScrnInfoPtr); +#ifdef XvExtension + void (*VideoTimerCallback)(ScrnInfoPtr, Time); + XF86VideoAdaptorPtr adaptor; + int videoKey; + int hsync; + int hsync_rskew; + int vsync; + int vsync_bskew; + CARD32 videoFlags; + int keyOffset; +#endif + int OverrideHsync; + int OverrideVsync; + int OverrideBskew; + int OverrideRskew; + OptionInfoPtr Options; + Bool shadowNew; + int displaySize; + int dspOverride; + Bool GammaBrightnessOn; + int brightness; + double gamma; + int FPDelay; /* just for debugging - will go away */ +} TRIDENTRec, *TRIDENTPtr; + +typedef struct { + CARD8 mode; + int display_x; + int display_y; + int clock; + int shadow_0; + int shadow_3; + int shadow_4; + int shadow_5; + int shadow_6; + int shadow_7; + int shadow_10; + int shadow_11; + int shadow_16; + int shadow_HiOrd; +} tridentLCD; + +#define LCD_ACTIVE 0x01 +#define CRT_ACTIVE 0x02 + +extern tridentLCD LCD[]; + +typedef struct { + int x_res; + int y_res; + int mode; +} biosMode; + +typedef struct { + int x_res; + int y_res; + CARD8 GR5a; + CARD8 GR5c; +} newModes; + +/* Prototypes */ + +Bool TRIDENTClockSelect(ScrnInfoPtr pScrn, int no); +Bool TRIDENTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +void TRIDENTAdjustFrame(int scrnIndex, int x, int y, int flags); +Bool TRIDENTDGAInit(ScreenPtr pScreen); +Bool TRIDENTI2CInit(ScreenPtr pScreen); +void TRIDENTInitVideo(ScreenPtr pScreen); +void TRIDENTResetVideo(ScrnInfoPtr pScrn); +unsigned int Tridentddc1Read(ScrnInfoPtr pScrn); +void TVGARestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg); +void TVGASave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg); +Bool TVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +void TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg); +void TridentSave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg); +Bool TridentInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +Bool TridentAccelInit(ScreenPtr pScreen); +Bool XPAccelInit(ScreenPtr pScreen); +Bool ImageAccelInit(ScreenPtr pScreen); +Bool BladeAccelInit(ScreenPtr pScreen); +Bool TridentHWCursorInit(ScreenPtr pScreen); +int TridentFindMode(int xres, int yres, int depth); +void TGUISetClock(ScrnInfoPtr pScrn, int clock, unsigned char *a, unsigned char *b); +void TGUISetMCLK(ScrnInfoPtr pScrn, int clock, unsigned char *a, unsigned char *b); +void tridentSetModeBIOS(ScrnInfoPtr pScrn, DisplayModePtr mode); +void TridentOutIndReg(ScrnInfoPtr pScrn, + CARD32 reg, unsigned char mask, unsigned char data); +unsigned char TridentInIndReg(ScrnInfoPtr pScrn, CARD32 reg); +void TridentWriteAddress(ScrnInfoPtr pScrn, CARD32 index); +void TridentReadAddress(ScrnInfoPtr pScrn, CARD32 index); +void TridentWriteData(ScrnInfoPtr pScrn, unsigned char data); +unsigned char TridentReadData(ScrnInfoPtr pScrn); +void TridentLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, VisualPtr pVisual); +void TridentSetOverscan(ScrnInfoPtr pScrn, int overscan); +int TGUISetRead(ScreenPtr pScreen, int bank); +int TGUISetWrite(ScreenPtr pScreen, int bank); +int TGUISetReadWrite(ScreenPtr pScreen, int bank); +int TVGA8900SetRead(ScreenPtr pScreen, int bank); +int TVGA8900SetWrite(ScreenPtr pScreen, int bank); +int TVGA8900SetReadWrite(ScreenPtr pScreen, int bank); +void TridentFindClock(ScrnInfoPtr pScrn, int clock); +float CalculateMCLK(ScrnInfoPtr pScrn); +void TRIDENTRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void TRIDENTShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf); +void TRIDENTPointerMoved(int index, int x, int y); +void TRIDENTRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void TRIDENTRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void TRIDENTRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void TRIDENTRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox); + +/* + * Trident Chipset Definitions + */ + +/* Supported chipsets */ +typedef enum { + TVGA8200LX, + TVGA8800BR, + TVGA8800CS, + TVGA8900B, + TVGA8900C, + TVGA8900CL, + TVGA8900D, + TVGA9000, + TVGA9000i, + TVGA9100B, + TVGA9200CXr, + TGUI9400CXi, + TGUI9420DGi, + TGUI9430DGi, + TGUI9440AGi, + CYBER9320, + TGUI9660, + TGUI9680, + PROVIDIA9682, + CYBER9382, + CYBER9385, + PROVIDIA9685, + CYBER9388, + CYBER9397, + CYBER9397DVD, + CYBER9520, + CYBER9525DVD, + IMAGE975, + IMAGE985, + BLADE3D, + CYBERBLADEI7, + CYBERBLADEI7D, + CYBERBLADEI1, + CYBERBLADEI1D, + CYBERBLADEAI1, + CYBERBLADEAI1D, + CYBERBLADEE4, + BLADEXP, + CYBERBLADEXPAI1 +} TRIDENTType; + +#define UseMMIO (pTrident->NoMMIO == FALSE) + +#define IsPciCard (pTrident->pEnt->location.type == BUS_PCI) + +#define IsPrimaryCard ((xf86IsPrimaryPci(pTrident->PciInfo)) || \ + (xf86IsPrimaryIsa())) + +#define HAS_DST_TRANS ((pTrident->Chipset == PROVIDIA9682) || \ + (pTrident->Chipset == PROVIDIA9685) || \ + (pTrident->Chipset == BLADEXP) || \ + (pTrident->Chipset == CYBERBLADEXPAI1)) + +#define Is3Dchip ((pTrident->Chipset == CYBER9397) || \ + (pTrident->Chipset == CYBER9397DVD) || \ + (pTrident->Chipset == CYBER9520) || \ + (pTrident->Chipset == CYBER9525DVD) || \ + (pTrident->Chipset == CYBERBLADEE4) || \ + (pTrident->Chipset == IMAGE975) || \ + (pTrident->Chipset == IMAGE985) || \ + (pTrident->Chipset == CYBERBLADEI7) || \ + (pTrident->Chipset == CYBERBLADEI7D) || \ + (pTrident->Chipset == CYBERBLADEI1) || \ + (pTrident->Chipset == CYBERBLADEI1D) || \ + (pTrident->Chipset == CYBERBLADEAI1) || \ + (pTrident->Chipset == CYBERBLADEAI1D) || \ + (pTrident->Chipset == BLADE3D) || \ + (pTrident->Chipset == CYBERBLADEXPAI1) || \ + (pTrident->Chipset == BLADEXP)) + +/* + * Trident DAC's + */ + +#define TKD8001 0 +#define TGUIDAC 1 + +/* + * Video Flags + */ + +#define VID_ZOOM_INV 0x1 +#define VID_ZOOM_MINI 0x2 +#define VID_OFF_SHIFT_4 0x4 +#define VID_ZOOM_NOMINI 0x8 +#define VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC 0x10 +#endif /* _TRIDENT_H_ */ + diff --git a/src/trident_accel.c b/src/trident_accel.c new file mode 100644 index 0000000..256e97e --- /dev/null +++ b/src/trident_accel.c @@ -0,0 +1,673 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * Trident accelerated options. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_accel.c,v 1.26 2003/02/12 21:46:42 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "miline.h" + +#include "trident.h" +#include "trident_regs.h" + +#include "xaalocal.h" +#include "xaarop.h" + +static void TridentSync(ScrnInfoPtr pScrn); +static void TridentSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int length, + unsigned char *pattern); +static void TridentSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant, int phase); +static void TridentSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void TridentSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant); +static void TridentSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, + int len, int dir); +static void TridentSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void TridentSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, + int y, int w, int h); +static void TridentSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, + int y2, int w, int h); +static void TridentSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int transparency_color); +static void TridentSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, int fg, int bg, + int rop, unsigned int planemask); +static void TridentSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#if 0 +static void TridentSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, unsigned int planemask, int trans_col); +static void TridentSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#endif +#if 0 +static void TridentSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void TridentSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft); +static void TridentSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); +#endif + + +static void +TridentInitializeAccelerator(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + /* This forces updating the clipper */ + pTrident->Clipping = TRUE; + + CHECKCLIPPING; + + if ( (pTrident->Chipset == PROVIDIA9682) || + (pTrident->Chipset == CYBER9385) || + (pTrident->Chipset == CYBER9382) ) + pTrident->EngineOperation |= 0x100; /* Disable Clipping */ + + TGUI_OPERMODE(pTrident->EngineOperation); + + pTrident->PatternLocation = pScrn->displayWidth*pScrn->bitsPerPixel/8; +} + +Bool +TridentAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + BoxRec AvailFBArea; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (pTrident->FbMapSize - 4096) / (pScrn->displayWidth * + pScrn->bitsPerPixel / 8); + + if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047; + + xf86InitFBManager(pScreen, &AvailFBArea); + + if (pTrident->NoAccel) + return FALSE; + + pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + if (!(pTrident->Chipset == TGUI9440AGi && pScrn->bitsPerPixel > 8)) + infoPtr->Flags = PIXMAP_CACHE | + OFFSCREEN_PIXMAPS | + LINEAR_FRAMEBUFFER; + + pTrident->InitializeAccelerator = TridentInitializeAccelerator; + TridentInitializeAccelerator(pScrn); + + infoPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES; + + infoPtr->Sync = TridentSync; + + infoPtr->SolidLineFlags = NO_PLANEMASK; + infoPtr->SetupForSolidLine = TridentSetupForSolidLine; + infoPtr->SolidBresenhamLineErrorTermBits = 12; + infoPtr->SubsequentSolidBresenhamLine = TridentSubsequentSolidBresenhamLine; + infoPtr->SubsequentSolidHorVertLine = TridentSubsequentSolidHorVertLine; + + infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | + NO_PLANEMASK | + LINE_PATTERN_POWER_OF_2_ONLY; + infoPtr->SetupForDashedLine = TridentSetupForDashedLine; + infoPtr->DashedBresenhamLineErrorTermBits = 12; + infoPtr->SubsequentDashedBresenhamLine = + TridentSubsequentDashedBresenhamLine; + infoPtr->DashPatternMaxLength = 16; + + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = TridentSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = TridentSubsequentFillRectSolid; + + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK; + + if (!HAS_DST_TRANS) infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; + + infoPtr->SetupForScreenToScreenCopy = + TridentSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + TridentSubsequentScreenToScreenCopy; + + if (!((pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) && pScrn->bitsPerPixel > 8)) { + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + + infoPtr->SetupForMono8x8PatternFill = + TridentSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + TridentSubsequentMono8x8PatternFillRect; + } + +#if 0 /* Not convinced this works 100% yet */ + infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + + if (!HAS_DST_TRANS) infoPtr->Color8x8PatternFillFlags |= NO_TRANSPARENCY; + + infoPtr->SetupForColor8x8PatternFill = + TridentSetupForColor8x8PatternFill; + infoPtr->SubsequentColor8x8PatternFillRect = + TridentSubsequentColor8x8PatternFillRect; +#endif + +#if 0 /* This is buggy, it only seems to work 95% of the time.... */ + { + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | + NO_TRANSPARENCY | + BIT_ORDER_IN_BYTE_MSBFIRST; + + pTrident->XAAScanlineColorExpandBuffers[0] = + xnfalloc(((pScrn->virtualX + 63)) *4* (pScrn->bitsPerPixel / 8)); + + infoPtr->NumScanlineColorExpandBuffers = 1; + infoPtr->ScanlineColorExpandBuffers = + pTrident->XAAScanlineColorExpandBuffers; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + TridentSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + TridentSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = + TridentSubsequentColorExpandScanline; + } +#endif + + return(XAAInit(pScreen, infoPtr)); +} + +static void +TridentSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count = 0, timeout = 0; + int busy; + + TGUI_OPERMODE(pTrident->EngineOperation); + + for (;;) { + BLTBUSY(busy); + if (busy != GE_BUSY) { + return; + } + count++; + if (count == 10000000) { + ErrorF("Trident: BitBLT engine time-out.\n"); + count = 9990000; + timeout++; + if (timeout == 8) { + /* Reset BitBLT Engine */ + TGUI_STATUS(0x00); + return; + } + } + } +} + +static void +TridentClearSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count = 0, timeout = 0; + int busy; + + for (;;) { + BLTBUSY(busy); + if (busy != GE_BUSY) { + return; + } + count++; + if (count == 10000000) { + ErrorF("Trident: BitBLT engine time-out.\n"); + count = 9990000; + timeout++; + if (timeout == 8) { + /* Reset BitBLT Engine */ + TGUI_STATUS(0x00); + return; + } + } + } +} + +static void +TridentSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int dst = 0; + + pTrident->BltScanDirection = 0; + if (xdir < 0) pTrident->BltScanDirection |= XNEG; + if (ydir < 0) pTrident->BltScanDirection |= YNEG; + + REPLICATE(transparency_color); + if (transparency_color != -1) { + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + dst |= 1<<16; + } else { + TGUI_OPERMODE(pTrident->EngineOperation | DST_ENABLE); + } + TGUI_CKEY(transparency_color); + } + + TGUI_DRAWFLAG(pTrident->DrawFlag | pTrident->BltScanDirection | SCR2SCR | dst); + TGUI_FMIX(XAACopyROP[rop]); +} + +static void +TridentSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (pTrident->BltScanDirection & YNEG) { + y1 = y1 + h - 1; + y2 = y2 + h - 1; + } + if (pTrident->BltScanDirection & XNEG) { + x1 = x1 + w - 1; + x2 = x2 + w - 1; + } + TGUI_SRC_XY(x1,y1); + TGUI_DEST_XY(x2,y2); + TGUI_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + TridentClearSync(pScrn); +} + +static void +TridentSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->BltScanDirection = 0; + REPLICATE(color); + TGUI_FMIX(XAAPatternROP[rop]); + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + TGUI_FPATCOL(color); + } else { + TGUI_FCOLOUR(color); + } +} + +static void +TridentSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp = pTrident->BltScanDirection; + + if (octant & YMAJOR) tmp |= YMAJ; + if (octant & XDECREASING) tmp |= XNEG; + if (octant & YDECREASING) tmp |= YNEG; + TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL | STENCIL | tmp); + TGUI_SRC_XY(dmin-dmaj,dmin); + TGUI_DEST_XY(x,y); + TGUI_DIM_XY(dmin+e,len); + TGUI_COMMAND(GE_BRESLINE); + TridentSync(pScrn); +} + +static void +TridentSubsequentSolidHorVertLine( + ScrnInfoPtr pScrn, + int x, int y, + int len, int dir +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL); + if (dir == DEGREES_0) { + TGUI_DIM_XY(len,1); + TGUI_DEST_XY(x,y); + } else { + TGUI_DIM_XY(1,len); + TGUI_DEST_XY(x,y); + } + TGUI_COMMAND(GE_BLT); + TridentSync(pScrn); +} + +void +TridentSetupForDashedLine( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int length, + unsigned char *pattern +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD32 *DashPattern = (CARD32*)pattern; + CARD32 NiceDashPattern = DashPattern[0]; + + NiceDashPattern = *((CARD16 *)pattern) & ((1<<length) - 1); + switch(length) { + case 2: NiceDashPattern |= NiceDashPattern << 2; + case 4: NiceDashPattern |= NiceDashPattern << 4; + case 8: NiceDashPattern |= NiceDashPattern << 8; + } + pTrident->BltScanDirection = 0; + REPLICATE(fg); + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + TGUI_FPATCOL(fg); + if (bg == -1) { + pTrident->BltScanDirection |= 1<<12; + TGUI_BPATCOL(~fg); + } else { + REPLICATE(bg); + TGUI_BPATCOL(bg); + } + } else { + TGUI_FCOLOUR(fg); + if (bg == -1) { + pTrident->BltScanDirection |= 1<<12; + TGUI_BCOLOUR(~fg); + } else { + REPLICATE(bg); + TGUI_BCOLOUR(bg); + } + } + TGUI_FMIX(XAAPatternROP[rop]); + pTrident->LinePattern = NiceDashPattern; +} + + +void +TridentSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp = pTrident->BltScanDirection; + + if (octant & YMAJOR) tmp |= YMAJ; + if (octant & XDECREASING) tmp |= XNEG; + if (octant & YDECREASING) tmp |= YNEG; + + TGUI_STYLE(((pTrident->LinePattern >> phase) | + (pTrident->LinePattern << (16-phase))) & 0x0000FFFF); + TGUI_DRAWFLAG(pTrident->DrawFlag | STENCIL | tmp); + TGUI_SRC_XY(dmin-dmaj,dmin); + TGUI_DEST_XY(x,y); + TGUI_DIM_XY(e+dmin,len); + TGUI_COMMAND(GE_BRESLINE); + TridentSync(pScrn); +} + +static void +TridentSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int drawflag = 0; + + REPLICATE(color); + TGUI_FMIX(XAAPatternROP[rop]); + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + TGUI_FPATCOL(color); + } else { + drawflag |= PATMONO; + TGUI_FCOLOUR(color); + } + TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL | drawflag); +} + +static void +TridentSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DIM_XY(w,h); + TGUI_DEST_XY(x,y); + TGUI_COMMAND(GE_BLT); + TridentSync(pScrn); +} + +#if 0 +static void MoveDWORDS( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + if (!dwords) return; + *dest = *src; + dest += 1; + src += 1; + if (dwords == 1) return; + *dest = *src; + dest += 1; + src += 1; + if (dwords == 2) return; + *dest = *src; + dest += 1; + src += 1; +} +#endif + +static void +TridentSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int drawflag = 0; + + REPLICATE(fg); + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) + TGUI_FPATCOL(fg); + else + TGUI_FCOLOUR(fg); + + if (bg == -1) { + drawflag |= 1<<12; + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) + TGUI_BPATCOL(~fg); + else + TGUI_BCOLOUR(~fg); + } else { + REPLICATE(bg); + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) + TGUI_BPATCOL(bg); + else + TGUI_BCOLOUR(bg); + } + + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + drawflag |= 7<<18; + } + TGUI_DRAWFLAG(pTrident->DrawFlag | PAT2SCR | PATMONO | drawflag); + TGUI_PATLOC(((patterny * pTrident->PatternLocation) + + (patternx * pScrn->bitsPerPixel / 8)) >> 6); + TGUI_FMIX(XAAPatternROP[rop]); +} + +static void +TridentSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DEST_XY(x,y); + TGUI_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + TridentSync(pScrn); +} + +#if 0 +static void +TridentSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int rop, + unsigned int planemask, + int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int drawflag = 0; + + REPLICATE(transparency_color); + if (transparency_color != -1) { + if (pTrident->Chipset == PROVIDIA9685 || + pTrident->Chipset == CYBER9388) { + drawflag |= 1<<16; + } else { + TGUI_OPERMODE(pTrident->EngineOperation | DST_ENABLE); + } + TGUI_CKEY(transparency_color); + } + + TGUI_DRAWFLAG(pTrident->DrawFlag | PAT2SCR | drawflag); + TGUI_PATLOC(((patterny * pTrident->PatternLocation) + + (patternx * pScrn->bitsPerPixel / 8)) >> 6); + TGUI_FMIX(XAAPatternROP[rop]); +} + +static void +TridentSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DEST_XY(x,y); + TGUI_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + TridentClearSync(pScrn); +} +#endif + +#if 0 +static void +TridentSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int drawflag = SRCMONO; + + REPLICATE(fg); + TGUI_FCOLOUR(fg); + if (bg == -1) { + drawflag |= 1<<12; + TGUI_BCOLOUR(~fg); + } else { + REPLICATE(bg); + TGUI_BCOLOUR(bg); + } + + TGUI_SRC_XY(0,0); + TGUI_DRAWFLAG(drawflag); + TGUI_FMIX(XAACopyROP[rop]); +} + +static void +TridentSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + pTrident->dwords = (w + 31) >> 5; + pTrident->h = h; + pTrident->y = y; + pTrident->x = x; + pTrident->w = w; + + TGUI_DEST_XY(x,pTrident->y++); + TGUI_DIM_XY(w,1); + TGUI_COMMAND(GE_BLT); +} + +static void +TridentSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XAAInfoRecPtr infoRec; + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + MoveDWORDS((CARD32 *)pTrident->FbBase, + (CARD32 *)pTrident->XAAScanlineColorExpandBuffers[0], + pTrident->dwords); + + pTrident->h--; + TridentSync(pScrn); + if (pTrident->h) { + TGUI_DEST_XY(pTrident->x,pTrident->y++); + TGUI_DIM_XY(pTrident->w,1); + TGUI_COMMAND(GE_BLT); + } +} +#endif diff --git a/src/trident_bank.c b/src/trident_bank.c new file mode 100644 index 0000000..056d64a --- /dev/null +++ b/src/trident_bank.c @@ -0,0 +1,95 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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_bank.c,v 1.4 2000/12/07 16:48:04 alanh Exp $ */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +#include "compiler.h" +#include "trident.h" +#include "trident_regs.h" + +int TVGA8900SetRead(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTW(0x3c4, 0xC000 | (((bank & 0x3f) ^ 0x02)<<8)|0x0E); + return 0; +} +int TGUISetRead(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTB(0x3d9, bank & 0xff); + return 0; +} +int TVGA8900SetWrite(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTW(0x3c4, 0xC000 | (((bank & 0x3f) ^ 0x02)<<8)|0x0E); + return 0; +} +int TGUISetWrite(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTB(0x3d8, bank & 0xff); + return 0; +} +int TVGA8900SetReadWrite(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTW(0x3c4, 0xC000 | (((bank & 0x3f) ^ 0x02)<<8)|0x0E); + return 0; +} +int TGUISetReadWrite(ScreenPtr pScreen, int bank) +{ + ScrnInfoPtr pScrn; + TRIDENTPtr pTrident; + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + OUTB(0x3d8, bank & 0xff); + OUTB(0x3d9, bank & 0xff); + return 0; +} diff --git a/src/trident_dac.c b/src/trident_dac.c new file mode 100644 index 0000000..311dd81 --- /dev/null +++ b/src/trident_dac.c @@ -0,0 +1,1200 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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.70 2003/01/05 18:09:00 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.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, 0x61 }, + { 1024, 768, 0x3b, 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 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; +} + +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; + Bool isShadow = 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) { + pReg->tridentRegs3x4[CRTHiOrd] = LCD[i].shadow_HiOrd; + } + + fullSize = (pScrn->currentMode->HDisplay == LCD[i].display_x) + && (pScrn->currentMode->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"); + isShadow = TRUE; + } 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; + isShadow = FALSE; + 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 */ + pReg->tridentRegs3CE[VertStretch] &= 0xFC; + pReg->tridentRegs3CE[VertStretch] |= 0x80; + pReg->tridentRegs3CE[HorStretch] &= 0xFC; + pReg->tridentRegs3CE[HorStretch] |= 0x80; +#if 1 + { + 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] = ((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( + pScrn->currentMode->HDisplay, + pScrn->currentMode->VDisplay, + pScrn->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, + "Setting BIOS Mode: %x\n", + pReg->tridentRegs3CE[BiosMode]); + } else { + TridentFindNewMode(pScrn->currentMode->HDisplay, + pScrn->currentMode->VDisplay, + &pReg->tridentRegs3CE[BiosNewMode1], + &pReg->tridentRegs3CE[BiosNewMode2]); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, + "Setting BIOS Mode Regs: %x %x\n", + pReg->tridentRegs3CE[BiosNewMode1], + pReg->tridentRegs3CE[BiosNewMode2]); + }; + + /* no stretch */ + if (pTrident->Chipset != CYBERBLADEXPAI1) + pReg->tridentRegs3CE[BiosReg] = 0; + else + pReg->tridentRegs3CE[BiosReg] = 8; + + 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 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: + if (pScrn->bitsPerPixel >= 8) + pReg->tridentRegs3CE[MiscExtFunc] |= 0x10; + else + 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 1: + case 4: + offset = pScrn->displayWidth >> 4; + break; + 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 == CYBERBLADEE4) { + OUTB(vgaIOBase+ 4, New32); + pReg->tridentRegs3x4[New32] = INB(vgaIOBase + 5) & 0x7F; + } + break; + case 32: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + if (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 == 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); + 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); + } + + return(TRUE); +} + +void +TridentRestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp; + 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); + temp = INB(0x3C5); + + /* Unprotect registers */ + OUTW(0x3C4, ((0xC0 ^ 0x02) << 8) | NewMode1); + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); + temp = 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 == CYBERBLADEE4) OUTW_3x4(New32); + 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); + CARD8 temp; + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + temp = 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 == CYBERBLADEE4) INB_3x4(New32); + 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); + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); + temp = 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; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + memcpy((CARD8 *)pTrident->FbBase + (pScrn->videoRam * 1024) - 4096, + src, pTrident->CursorInfoRec->MaxWidth * + pTrident->CursorInfoRec->MaxHeight / 4); + + OUTW(vgaIOBase + 4, (((pScrn->videoRam-4) & 0xFF) << 8) | 0x44); + OUTW(vgaIOBase + 4, ((pScrn->videoRam-4) & 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; +} + +Bool +TridentHWCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + xf86CursorInfoPtr infoPtr; + int memory = pScrn->displayWidth * pScrn->virtualY * pScrn->bitsPerPixel/8; + + if (memory > (pScrn->videoRam * 1024 - 4096)) 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 == 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); + } +} + diff --git a/src/trident_dga.c b/src/trident_dga.c new file mode 100644 index 0000000..4045194 --- /dev/null +++ b/src/trident_dga.c @@ -0,0 +1,275 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dga.c,v 1.4 2002/10/08 22:14:11 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xaalocal.h" +#include "trident.h" +#include "trident_regs.h" +#include "dgaproc.h" + + +static Bool TRIDENT_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool TRIDENT_SetMode(ScrnInfoPtr, DGAModePtr); +static void TRIDENT_Sync(ScrnInfoPtr); +static int TRIDENT_GetViewport(ScrnInfoPtr); +static void TRIDENT_SetViewport(ScrnInfoPtr, int, int, int); +static void TRIDENT_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void TRIDENT_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +#if 0 +static void TRIDENT_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); +#endif + +static +DGAFunctionRec TRIDENTDGAFuncs = { + TRIDENT_OpenFramebuffer, + NULL, + TRIDENT_SetMode, + TRIDENT_SetViewport, + TRIDENT_GetViewport, + TRIDENT_Sync, + TRIDENT_FillRect, + TRIDENT_BlitRect, +#if 0 + TRIDENT_BlitTransRect +#else + NULL +#endif +}; + +Bool +TRIDENTDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + DGAModePtr modes = NULL, newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int Bpp = pScrn->bitsPerPixel >> 3; + int num = 0; + Bool oneMore; + + pMode = firstMode = pScrn->modes; + + while(pMode) { + + if(0 /*pScrn->displayWidth != pMode->HDisplay*/) { + newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + } else { + newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + } + + if(!newmodes) { + xfree(modes); + return FALSE; + } + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + num; + num++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; + if(!pTrident->NoAccel) + currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if(pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if(pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = pScrn->depth; + currentMode->bitsPerPixel = pScrn->bitsPerPixel; + currentMode->red_mask = pScrn->mask.red; + currentMode->green_mask = pScrn->mask.green; + currentMode->blue_mask = pScrn->mask.blue; + currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = 1; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE; + currentMode->offset = 0; + currentMode->address = pTrident->FbBase; + + if(oneMore) { /* first one is narrow width */ + currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L; + currentMode->imageWidth = pMode->HDisplay; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + oneMore = FALSE; + goto SECOND_PASS; + } else { + currentMode->bytesPerScanline = + ((pScrn->displayWidth * Bpp) + 3) & ~3L; + currentMode->imageWidth = pScrn->displayWidth; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + } + + pMode = pMode->next; + if(pMode == firstMode) + break; + } + + pTrident->numDGAModes = num; + pTrident->DGAModes = modes; + + return DGAInit(pScreen, &TRIDENTDGAFuncs, modes, num); +} + + +static Bool +TRIDENT_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static int OldDisplayWidth[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if(!pMode) { /* restore the original mode */ + /* put the ScreenParameters back */ + + pScrn->displayWidth = OldDisplayWidth[index]; + + TRIDENTSwitchMode(index, pScrn->currentMode, 0); + pTrident->DGAactive = FALSE; + } else { + if(!pTrident->DGAactive) { /* save the old parameters */ + OldDisplayWidth[index] = pScrn->displayWidth; + + pTrident->DGAactive = TRUE; + } + + pScrn->displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + + TRIDENTSwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + + + +static int +TRIDENT_GetViewport( + ScrnInfoPtr pScrn +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + return pTrident->DGAViewportStatus; +} + +static void +TRIDENT_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TRIDENTAdjustFrame(pScrn->pScreen->myNum, x, y, flags); + pTrident->DGAViewportStatus = 0; /* TRIDENTAdjustFrame loops until finished */ +} + +static void +TRIDENT_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if(pTrident->AccelInfoRec) { + (*pTrident->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pTrident->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(pTrident->AccelInfoRec); + } +} + +static void +TRIDENT_Sync( + ScrnInfoPtr pScrn +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if(pTrident->AccelInfoRec) { + (*pTrident->AccelInfoRec->Sync)(pScrn); + } +} + +static void +TRIDENT_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if(pTrident->AccelInfoRec) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pTrident->AccelInfoRec->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, -1); + (*pTrident->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pTrident->AccelInfoRec); + } +} + +#if 0 +static void +TRIDENT_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + /* this one should be separate since the XAA function would + prohibit usage of ~0 as the key */ +} +#endif + +static Bool +TRIDENT_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)pTrident->FbAddress; + *size = pTrident->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/trident_driver.c b/src/trident_driver.c new file mode 100644 index 0000000..a75d4fe --- /dev/null +++ b/src/trident_driver.c @@ -0,0 +1,3632 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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 + * Re-written for XFree86 v4.0 + * + * Previous driver (pre-XFree86 v4.0) by + * Alan Hourihane, alanh@fairlite.demon.co.uk + * David Wexelblat (major contributor) + * Massimiliano Ghilardi, max@Linuz.sns.it, some fixes to the + * clockchip programming code. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_driver.c,v 1.176 2003/02/11 03:41:38 dawes Exp $ */ + +#include "xf1bpp.h" +#include "xf4bpp.h" +#include "fb.h" + +#include "mibank.h" +#include "micmap.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86cmap.h" +#include "vgaHW.h" +#include "xf86RAC.h" +#include "vbe.h" +#include "dixstruct.h" +#include "compiler.h" + +#include "mipointer.h" + +#include "mibstore.h" +#include "shadow.h" +#include "trident.h" +#include "trident_regs.h" + +#define _XF86DGA_SERVER_ +#include "extensions/xf86dgastr.h" + +#include "globals.h" +#define DPMS_SERVER +#include "extensions/dpms.h" + +#ifdef XvExtension +#include "xf86xv.h" +#endif + +static const OptionInfoRec * TRIDENTAvailableOptions(int chipid, int busid); +static void TRIDENTIdentify(int flags); +static Bool TRIDENTProbe(DriverPtr drv, int flags); +static Bool TRIDENTPreInit(ScrnInfoPtr pScrn, int flags); +static Bool TRIDENTScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool TRIDENTEnterVT(int scrnIndex, int flags); +static void TRIDENTLeaveVT(int scrnIndex, int flags); +static Bool TRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool TRIDENTSaveScreen(ScreenPtr pScreen, int mode); + +/* Optional functions */ +static void TRIDENTFreeScreen(int scrnIndex, int flags); +static int TRIDENTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags); + +/* Internally used functions */ +static Bool TRIDENTMapMem(ScrnInfoPtr pScrn); +static Bool TRIDENTUnmapMem(ScrnInfoPtr pScrn); +static void TRIDENTSave(ScrnInfoPtr pScrn); +static void TRIDENTRestore(ScrnInfoPtr pScrn); +static Bool TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void TRIDENTBlockHandler(int, pointer, pointer, pointer); + +static void TRIDENTEnableMMIO(ScrnInfoPtr pScrn); +static void TRIDENTDisableMMIO(ScrnInfoPtr pScrn); +static void PC98TRIDENTInit(ScrnInfoPtr pScrn); +static void PC98TRIDENTEnable(ScrnInfoPtr pScrn); +static void PC98TRIDENTDisable(ScrnInfoPtr pScrn); +static void PC98TRIDENT96xxInit(ScrnInfoPtr pScrn); +static void PC98TRIDENT96xxEnable(ScrnInfoPtr pScrn); +static void PC98TRIDENT96xxDisable(ScrnInfoPtr pScrn); +static void PC98TRIDENT9385Init(ScrnInfoPtr pScrn); +static void PC98TRIDENT9385Enable(ScrnInfoPtr pScrn); +static void PC98TRIDENT9385Disable(ScrnInfoPtr pScrn); + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +#define VERSION 4000 +#define TRIDENT_NAME "TRIDENT" +#define TRIDENT_DRIVER_NAME "trident" +#define TRIDENT_MAJOR_VERSION 1 +#define TRIDENT_MINOR_VERSION 0 +#define TRIDENT_PATCHLEVEL 0 + +/* + * This contains the functions needed by the server after loading the driver + * module. It must be supplied, and gets passed back by the SetupProc + * function in the dynamic case. In the static case, a reference to this + * is compiled in, and this requires that the name of this DriverRec be + * an upper-case version of the driver name. + */ + +DriverRec TRIDENT = { + VERSION, + TRIDENT_DRIVER_NAME, + TRIDENTIdentify, + TRIDENTProbe, + TRIDENTAvailableOptions, + NULL, + 0 +}; + +static SymTabRec TRIDENTChipsets[] = { + { TVGA9000, "tvga9000" }, + { TVGA9000i, "tvga9000i" }, + { TVGA8900C, "tvga8900c" }, + { TVGA8900D, "tvga8900d" }, + { TVGA9200CXr, "tvga9200cxr" }, + { TGUI9400CXi, "tgui9400cxi" }, + { CYBER9320, "cyber9320" }, + { CYBER9388, "cyber9388" }, + { CYBER9397, "cyber9397" }, + { CYBER9397DVD, "cyber9397dvd" }, + { CYBER9520, "cyber9520" }, + { CYBER9525DVD, "cyber9525dvd" }, + { CYBERBLADEE4, "cyberblade/e4" }, + { TGUI9420DGi, "tgui9420dgi" }, + { TGUI9440AGi, "tgui9440agi" }, + { TGUI9660, "tgui9660" }, + { TGUI9680, "tgui9680" }, + { PROVIDIA9682, "providia9682" }, + { PROVIDIA9685, "providia9685" }, + { CYBER9382, "cyber9382" }, + { CYBER9385, "cyber9385" }, + { IMAGE975, "3dimage975" }, + { IMAGE985, "3dimage985" }, + { BLADE3D, "blade3d" }, + { CYBERBLADEI7, "cyberbladei7" }, + { CYBERBLADEI7D, "cyberbladei7d" }, + { CYBERBLADEI1, "cyberbladei1" }, + { CYBERBLADEI1D, "cyberbladei1d" }, + { CYBERBLADEAI1, "cyberbladeAi1" }, + { CYBERBLADEAI1D, "cyberbladeAi1d" }, + { BLADEXP, "bladeXP" }, + { CYBERBLADEXPAI1, "cyberbladeXPAi1" }, + { -1, NULL } +}; + +static IsaChipsets TRIDENTISAchipsets[] = { + { TVGA9000, RES_EXCLUSIVE_VGA }, + { TVGA9000i, RES_EXCLUSIVE_VGA }, + { TVGA8900C, RES_EXCLUSIVE_VGA }, + { TVGA8900D, RES_EXCLUSIVE_VGA }, + { TVGA9200CXr, RES_EXCLUSIVE_VGA }, + { TGUI9400CXi, RES_EXCLUSIVE_VGA }, + { CYBER9320, RES_EXCLUSIVE_VGA }, + { TGUI9440AGi, RES_EXCLUSIVE_VGA }, + { -1, RES_UNDEFINED } +}; + +static PciChipsets TRIDENTPciChipsets[] = { + { CYBER9320, PCI_CHIP_9320, RES_SHARED_VGA }, + { CYBER9388, PCI_CHIP_9388, RES_SHARED_VGA }, + { CYBER9397, PCI_CHIP_9397, RES_SHARED_VGA }, + { CYBER9397DVD, PCI_CHIP_939A, RES_SHARED_VGA }, + { CYBER9520, PCI_CHIP_9520, RES_SHARED_VGA }, + { CYBER9525DVD, PCI_CHIP_9525, RES_SHARED_VGA }, + { CYBERBLADEE4, PCI_CHIP_9540, RES_SHARED_VGA }, + { TGUI9420DGi, PCI_CHIP_9420, RES_SHARED_VGA }, + { TGUI9440AGi, PCI_CHIP_9440, RES_SHARED_VGA }, + { TGUI9660, PCI_CHIP_9660, RES_SHARED_VGA }, + { TGUI9680, PCI_CHIP_9660, RES_SHARED_VGA }, + { PROVIDIA9682, PCI_CHIP_9660, RES_SHARED_VGA }, + { PROVIDIA9685, PCI_CHIP_9660, RES_SHARED_VGA }, + { CYBER9382, PCI_CHIP_9660, RES_SHARED_VGA }, + { CYBER9385, PCI_CHIP_9660, RES_SHARED_VGA }, + { IMAGE975, PCI_CHIP_9750, RES_SHARED_VGA }, + { IMAGE985, PCI_CHIP_9850, RES_SHARED_VGA }, + { BLADE3D, PCI_CHIP_9880, RES_SHARED_VGA }, + { CYBERBLADEI7, PCI_CHIP_8400, RES_SHARED_VGA }, + { CYBERBLADEI7D, PCI_CHIP_8420, RES_SHARED_VGA }, + { CYBERBLADEI1, PCI_CHIP_8500, RES_SHARED_VGA }, + { CYBERBLADEI1D, PCI_CHIP_8520, RES_SHARED_VGA }, + { CYBERBLADEAI1, PCI_CHIP_8600, RES_SHARED_VGA }, + { CYBERBLADEAI1D, PCI_CHIP_8620, RES_SHARED_VGA }, + { BLADEXP, PCI_CHIP_9910, RES_SHARED_VGA }, + { CYBERBLADEXPAI1, PCI_CHIP_8820, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } +}; + +typedef enum { + OPTION_SW_CURSOR, + OPTION_PCI_RETRY, + OPTION_RGB_BITS, + OPTION_NOACCEL, + OPTION_SETMCLK, + OPTION_MUX_THRESHOLD, + OPTION_SHADOW_FB, + OPTION_ROTATE, + OPTION_MMIO_ONLY, + OPTION_VIDEO_KEY, + OPTION_NOMMIO, + OPTION_NOPCIBURST, + OPTION_CYBER_SHADOW, + OPTION_CYBER_STRETCH, + OPTION_XV_HSYNC, + OPTION_XV_VSYNC, + OPTION_XV_BSKEW, + OPTION_XV_RSKEW, + OPTION_FP_DELAY, + OPTION_1400_DISPLAY, + OPTION_DISPLAY, + OPTION_GB +} TRIDENTOpts; + +static const OptionInfoRec TRIDENTOptions[] = { + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SETMCLK, "SetMClk", OPTV_FREQ, {0}, FALSE }, + { OPTION_MUX_THRESHOLD, "MUXThreshold", OPTV_INTEGER, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_NOMMIO, "NoMMIO", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOPCIBURST, "NoPciBurst", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MMIO_ONLY, "MMIOonly", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CYBER_SHADOW, "CyberShadow", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CYBER_STRETCH, "CyberStretch", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XV_HSYNC, "XvHsync", OPTV_INTEGER, {0}, FALSE }, + { OPTION_XV_VSYNC, "XvVsync", OPTV_INTEGER, {0}, FALSE }, + { OPTION_XV_BSKEW, "XvBskew", OPTV_INTEGER, {0}, FALSE }, + { OPTION_XV_RSKEW, "XvRskew", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FP_DELAY, "FpDelay", OPTV_INTEGER, {0}, FALSE }, + { OPTION_1400_DISPLAY, "Display1400", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DISPLAY, "Display", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_GB, "GammaBrightness", OPTV_ANYSTR, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* Clock Limits */ +static int ClockLimit[] = { + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 90000, + 90000, + 135000, + 135000, + 170000, + 170000, + 170000, + 170000, + 170000, + 170000, + 170000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, +}; + +static int ClockLimit16bpp[] = { + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 45000, + 45000, + 90000, + 90000, + 135000, + 135000, + 170000, + 170000, + 170000, + 170000, + 170000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, +}; + +static int ClockLimit24bpp[] = { + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 40000, + 40000, + 70000, + 70000, + 70000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, +}; + +static int ClockLimit32bpp[] = { + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 40000, + 40000, + 70000, + 70000, + 70000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, +}; + +/* + * These are fixed modelines for all physical display dimensions the + * chipsets supports on FPs. Most of them are not tested yet. + */ +#if 0 +tridentLCD LCD[] = { /* 0 3 4 5 6 7 10 11 16 */ + { 0,"640x480",25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08}, + { 1,"800x600",40000,0x7f,0x99,0x69,0x99,0x72,0xf0,0x59,0x2d,0x5e,0x08}, + { 2,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, + { 3,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, /*0x96*/ + { 4,"1280x1024",108000,0xa3,0x6,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, + { 5,"1024x600",50500 ,0xa3,0x6,0x8f,0xa0,0xb,0x3e,0xea,0x8c,0xb,0x08}, + { 0xff,"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; +#else +#if 0 +tridentLCD LCD[] = { + { 1,640,480,25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08}, + { 3,800,600,40000,0x7f,0x82,0x6b,0x1b,0x72,0xf8,0x58,0x8c,0x72,0x08}, + { 2,1024,768,65000,0xa3,/*0x6*/0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x24,0x0a,0x08}, + { 0,1280,1024,108000,0xce,0x81,0xa6,0x9a,0x27,0x50,0x00,0x03,0x26,0xa8}, + { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; +#else +tridentLCD LCD[] = { + { 1,640,480,25200,0x5f,0x80,0x52,0x1e,0xb,0x3e,0xea,0x0c,0xb,0x08}, + { 3,800,600,40000,0x7f,0x00,0x69,0x7f,0x72,0xf0,0x59,0x0d,0x00,0x08}, + { 2,1024,768,65000,0xa3,0x00,0x84,0x94,0x24,0xf5,0x03,0x09,0x24,0x08}, + { 0,1280,1024,108000,0xce,0x91,0xa6,0x14,0x28,0x5a,0x01,0x04,0x28,0xa8}, + { 4,1400,1050,122000,0xe6,0xcd,0xba,0x1d,0x38,0x00,0x1c,0x28,0x28,0xf8}, + { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; +#endif +#endif + +static const char *xaaSymbols[] = { + "XAACopyROP", + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAFillSolidRects", + "XAAInit", + "XAAPatternROP", + "XAAScreenIndex", + NULL +}; + +static const char *vgahwSymbols[] = { + "vgaHWBlankScreen", + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWLock", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWSetMmioFuncs", + "vgaHWUnlock", + NULL +}; + +static const char *miscfbSymbols[] = { + "xf1bppScreenInit", + "xf4bppScreenInit", + NULL +}; + +static const char *fbSymbols[] = { + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86SetDDCproperties", + NULL +}; + +static const char *i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + NULL +}; + +static const char *int10Symbols[] = { + "xf86ExecX86int10", + "xf86FreeInt10", + "xf86InitInt10", + NULL +}; + +static const char *shadowSymbols[] = { + "shadowInit", + NULL +}; + +static const char *vbeSymbols[] = { + "VBEInit", + "vbeDoEDID", + "vbeFree", + NULL +}; + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(tridentSetup); + +static XF86ModuleVersionInfo tridentVersRec = +{ + "trident", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + TRIDENT_MAJOR_VERSION, TRIDENT_MINOR_VERSION, TRIDENT_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + +XF86ModuleData tridentModuleData = { &tridentVersRec, tridentSetup, NULL }; + +pointer +tridentSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&TRIDENT, module, 0); + LoaderRefSymLists(vgahwSymbols, fbSymbols, i2cSymbols, vbeSymbols, + miscfbSymbols, ramdacSymbols, int10Symbols, + xaaSymbols, shadowSymbols, NULL); + return (pointer)TRUE; + } + + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; +} + +#endif /* XFree86LOADER */ + +static Bool +TRIDENTGetRec(ScrnInfoPtr pScrn) +{ + /* + * Allocate an TRIDENTRec, and hook it into pScrn->driverPrivate. + * pScrn->driverPrivate is initialised to NULL, so we can check if + * the allocation has already been done. + */ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(TRIDENTRec), 1); + /* Initialise it */ + + return TRUE; +} + +static void +TRIDENTFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +static void +TRIDENTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 DPMSCont, PMCont, temp; + + if (!pScrn->vtSema) + return; + + OUTB(0x3C4, 0x0E); + temp = INB(0x3C5); + OUTB(0x3C5, 0xC2); + OUTB(0x83C8, 0x04); /* Read DPMS Control */ + PMCont = INB(0x83C6) & 0xFC; + OUTB(0x3CE, 0x23); + DPMSCont = INB(0x3CF) & 0xFC; + switch (PowerManagementMode) + { + case DPMSModeOn: + /* Screen: On, HSync: On, VSync: On */ + PMCont |= 0x03; + DPMSCont |= 0x00; + break; + case DPMSModeStandby: + /* Screen: Off, HSync: Off, VSync: On */ + PMCont |= 0x02; + DPMSCont |= 0x01; + break; + case DPMSModeSuspend: + /* Screen: Off, HSync: On, VSync: Off */ + PMCont |= 0x02; + DPMSCont |= 0x02; + break; + case DPMSModeOff: + /* Screen: Off, HSync: Off, VSync: Off */ + PMCont |= 0x00; + DPMSCont |= 0x03; + break; + } + OUTB(0x3CF, DPMSCont); + OUTB(0x83C8, 0x04); + OUTB(0x83C6, PMCont); + OUTW(0x3C4, (temp<<8) | 0x0E); +} + +static void +TRIDENTBlockHandler ( + int i, + pointer blockData, + pointer pTimeout, + pointer pReadmask +){ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrn = xf86Screens[i]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pScreen->BlockHandler = pTrident->BlockHandler; + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = TRIDENTBlockHandler; + + if(pTrident->VideoTimerCallback) { + UpdateCurrentTime(); + (*pTrident->VideoTimerCallback)(pScrn, currentTime.milliseconds); + } +} + +static const OptionInfoRec * +TRIDENTAvailableOptions(int chipid, int busid) +{ + return TRIDENTOptions; +} + +/* Mandatory */ +static void +TRIDENTIdentify(int flags) +{ + xf86PrintChipsets(TRIDENT_NAME, "driver for Trident chipsets", TRIDENTChipsets); +} + +static void +TRIDENTFix1bpp(ScrnInfoPtr pScrn) { + vgaHWPtr hwp = VGAHWPTR(pScrn); +/* In 1 bpp we have color 0 at LUT 0 and color 1 at LUT 0x3f. + This makes white and black look right (otherwise they were both + black. I'm sure there's a better way to do that, just lazy to + search the docs. */ + + (*hwp->writeDacWriteAddr)(hwp, 0x00); + (*hwp->writeDacData)(hwp, 0x00); + (*hwp->writeDacData)(hwp, 0x00); + (*hwp->writeDacData)(hwp, 0x00); + + (*hwp->writeDacWriteAddr)(hwp, 0x3F); + (*hwp->writeDacData)(hwp, 0x3F); + (*hwp->writeDacData)(hwp, 0x3F); + (*hwp->writeDacData)(hwp, 0x3F); +} + +Bool +TRIDENTClockSelect(ScrnInfoPtr pScrn, int no) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + unsigned char temp; + + /* + * CS0 and CS1 are in MiscOutReg + * + * For 8900B, 8900C, 8900CL and 9000, CS2 is bit 0 of + * New Mode Control Register 2. + * + * For 8900CL, CS3 is bit 4 of Old Mode Control Register 1. + * + * For 9000, CS3 is bit 6 of New Mode Control Register 2. + * + * For TGUI, we don't use the ClockSelect function at all. + */ + switch(no) { + case CLK_REG_SAVE: + pTrident->SaveClock1 = INB(0x3CC); + if (pTrident->Chipset != TVGA8800CS) { + if ( (pScrn->numClocks == 16) && + (pTrident->Chipset != TVGA9000) && + (pTrident->Chipset != TVGA9000i) ) + { + OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ + OUTB(0x3C4, 0x0E); pTrident->SaveClock3 = INB(0x3C5); + } + OUTB(0x3C4, 0x0B); + INB(0x3C5); /* Now to New Mode */ + OUTB(0x3C4, 0x0D); pTrident->SaveClock2 = INB(0x3C5); + } + break; + case CLK_REG_RESTORE: + OUTB(0x3C2, pTrident->SaveClock1); + if (pTrident->Chipset != TVGA8800CS) { + if ( (pScrn->numClocks == 16) && + (pTrident->Chipset != TVGA9000) && + (pTrident->Chipset != TVGA9000i) ) + { + OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ + OUTW(0x3C4, (pTrident->SaveClock3 << 8) | 0x0E); + } + OUTB(0x3C4, 0x0B); + INB(0x3C5); /* Now to New Mode */ + OUTW(0x3C4, (pTrident->SaveClock2 << 8) | 0x0D); + } + break; + default: + /* + * Do CS0 and CS1 + */ + temp = INB(0x3CC); + OUTB(0x3C2, (temp & 0xF3) | ((no << 2) & 0x0C)); + if (pTrident->Chipset != TVGA8800CS) { + if ( (pScrn->numClocks == 16) && + (pTrident->Chipset != TVGA9000) && + (pTrident->Chipset != TVGA9000i) ) + { + /* + * Go to Old Mode for CS3. + */ + OUTW(0x3C4, 0x000B); /* Switch to Old Mode */ + OUTB(0x3C4, 0x0E); + temp = INB(0x3C5) & 0xEF; + temp |= (no & 0x08) << 1; + OUTB(0x3C5, temp); + } + /* + * Go to New Mode for CS2 and TVGA9000 CS3. + */ + OUTB(0x3C4, 0x0B); + INB(0x3C5); /* Now to New Mode */ + OUTB(0x3C4, 0x0D); + /* + * Bits 1 & 2 are dividers - set to 0 to get no + * clock division. + */ + temp = INB(0x3C5) & 0xF8; + temp |= (no & 0x04) >> 2; + if ( (pTrident->Chipset == TVGA9000) || + (pTrident->Chipset == TVGA9000i) ) + { + temp &= ~0x40; + temp |= (no & 0x08) << 3; + } + OUTB(0x3C5, temp); + } + } + return(TRUE); +} + +static int +TridentFindIsaDevice(GDevPtr dev) +{ + int found = -1; + unsigned char temp, origVal, newVal; + + /* + * Check first that we have a Trident card. + */ + outb(0x3C4, 0x0B); + temp = inb(0x3C5); /* Save old value */ + outb(0x3C4, 0x0B); /* Switch to Old Mode */ + outb(0x3C5, 0x00); + inb(0x3C5); /* Now to New Mode */ + outb(0x3C4, 0x0E); + origVal = inb(0x3C5); + outb(0x3C5, 0x00); + newVal = inb(0x3C5) & 0x0F; + outb(0x3C5, (origVal ^ 0x02)); + + /* + * Is it a Trident card ?? + */ + if (newVal != 2) { + /* + * Nope, so quit + */ + outb(0x3C4, 0x0B); /* Restore value of 0x0B */ + outb(0x3C5, temp); + outb(0x3C4, 0x0E); + outb(0x3C5, origVal); + return found; + } + + outb(0x3C4, 0x0B); + temp = inb(0x3C5); + switch (temp) { + case 0x01: + found = TVGA8800BR; + break; + case 0x02: + found = TVGA8800CS; + break; + case 0x03: + found = TVGA8900B; + break; + case 0x04: + case 0x13: + found = TVGA8900C; + break; + case 0x23: + found = TVGA9000; + break; + case 0x33: + found = TVGA8900D; + break; + case 0x43: + found = TVGA9000i; + break; + case 0x53: + found = TVGA9200CXr; + break; + case 0x63: + found = TVGA9100B; + break; + case 0x73: + case 0xC3: + found = TGUI9420DGi; + break; + case 0x83: + found = TVGA8200LX; + break; + case 0x93: + found = TGUI9400CXi; + break; + case 0xA3: + found = CYBER9320; + break; + case 0xD3: + found = TGUI9660; + break; + case 0xE3: + found = TGUI9440AGi; + break; + case 0xF3: + found = TGUI9430DGi; + break; + } + return found; +} + + +/* Mandatory */ +static Bool +TRIDENTProbe(DriverPtr drv, int flags) +{ + int i; + GDevPtr *devSections; + int *usedChips = NULL; + int numDevSections; + int numUsed; + Bool foundScreen = FALSE; + + if ((numDevSections = xf86MatchDevice(TRIDENT_DRIVER_NAME, + &devSections)) <= 0) { + /* + * There's no matching device section in the config file, so quit + * now. + */ + return FALSE; + } + + /* + * While we're VGA-dependent, can really only have one such instance, but + * we'll ignore that. + */ + + /* + * We need to probe the hardware first. We then need to see how this + * fits in with what is given in the config file, and allow the config + * file info to override any contradictions. + */ + + /* + * All of the cards this driver supports are PCI, so the "probing" just + * amounts to checking the PCI data that the server has already collected. + */ + if (xf86GetPciVideoInfo()) { + numUsed = xf86MatchPciInstances(TRIDENT_NAME, PCI_VENDOR_TRIDENT, + TRIDENTChipsets, TRIDENTPciChipsets, devSections, + numDevSections, drv, &usedChips); + + if (numUsed > 0) { + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + + if ((pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i], + TRIDENTPciChipsets, NULL, + NULL, NULL, NULL, NULL))) { + /* Fill in what we can of the ScrnInfoRec */ + pScrn->driverVersion = VERSION; + pScrn->driverName = TRIDENT_DRIVER_NAME; + pScrn->name = TRIDENT_NAME; + pScrn->Probe = TRIDENTProbe; + pScrn->PreInit = TRIDENTPreInit; + pScrn->ScreenInit = TRIDENTScreenInit; + pScrn->SwitchMode = TRIDENTSwitchMode; + pScrn->AdjustFrame = TRIDENTAdjustFrame; + pScrn->EnterVT = TRIDENTEnterVT; + pScrn->LeaveVT = TRIDENTLeaveVT; + pScrn->FreeScreen = TRIDENTFreeScreen; + pScrn->ValidMode = TRIDENTValidMode; + foundScreen = TRUE; + } + } + xfree(usedChips); + } + } + + /* Isa Bus */ + numUsed = xf86MatchIsaInstances(TRIDENT_NAME,TRIDENTChipsets, + TRIDENTISAchipsets, + drv,TridentFindIsaDevice,devSections, + numDevSections,&usedChips); + if (numUsed > 0) { + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigIsaEntity(pScrn,0,usedChips[i], + TRIDENTISAchipsets,NULL, + NULL,NULL,NULL,NULL))) { + pScrn->driverVersion = VERSION; + pScrn->driverName = TRIDENT_DRIVER_NAME; + pScrn->name = TRIDENT_NAME; + pScrn->Probe = TRIDENTProbe; + pScrn->PreInit = TRIDENTPreInit; + pScrn->ScreenInit = TRIDENTScreenInit; + pScrn->SwitchMode = TRIDENTSwitchMode; + pScrn->AdjustFrame = TRIDENTAdjustFrame; + pScrn->EnterVT = TRIDENTEnterVT; + pScrn->LeaveVT = TRIDENTLeaveVT; + pScrn->FreeScreen = TRIDENTFreeScreen; + pScrn->ValidMode = TRIDENTValidMode; + foundScreen = TRUE; + } + } + xfree(usedChips); + } + + xfree(devSections); + return foundScreen; +} + +/* + * GetAccelPitchValues - + * + * This function returns a list of display width (pitch) values that can + * be used in accelerated mode. + */ +static int * +GetAccelPitchValues(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int *linePitches = NULL; + int lines[4] = { 512, 1024, 2048, 4096 }; /* 9440AGi */ + int i, n = 0; + + if (pTrident->Chipset >= BLADEXP) { + lines[0] = 1024; + lines[1] = 2048; + lines[2] = 4096; + lines[3] = 8192; + } + + for (i = 0; i < 4; i++) { + n++; + linePitches = xnfrealloc(linePitches, n * sizeof(int)); + linePitches[n - 1] = lines[i]; + } + + /* Mark the end of the list */ + if (n > 0) { + linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int)); + linePitches[n] = 0; + } + return linePitches; +} + +static void +TRIDENTProbeDDC(ScrnInfoPtr pScrn, int index) +{ + vbeInfoPtr pVbe; + if (xf86LoadSubModule(pScrn, "vbe")) { + pVbe = VBEInit(NULL,index); + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } +} + +/* Mandatory */ +static Bool +TRIDENTPreInit(ScrnInfoPtr pScrn, int flags) +{ + TRIDENTPtr pTrident; + vgaHWPtr hwp; + MessageType from; + CARD8 videoram, videorammask; + char *ramtype = NULL, *chipset = NULL; + Bool Support24bpp; + int vgaIOBase; + float mclk; + double real; + int i, NoClocks = 16; + CARD8 revision; + ClockRangePtr clockRanges; + char *mod = NULL; + const char *Sym = ""; + Bool ddcLoaded = FALSE; + char *s; + + /* Allocate the TRIDENTRec driverPrivate */ + if (!TRIDENTGetRec(pScrn)) { + return FALSE; + } + pTrident = TRIDENTPTR(pScrn); + pTrident->pScrn = pScrn; + + if (pScrn->numEntities > 1) + return FALSE; + /* This is the general case */ + for (i = 0; i<pScrn->numEntities; i++) { + pTrident->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); + if (pTrident->pEnt->resources) return FALSE; + pTrident->Chipset = pTrident->pEnt->chipset; + pScrn->chipset = (char *)xf86TokenToString(TRIDENTChipsets, + pTrident->pEnt->chipset); + /* This driver can handle ISA and PCI buses */ + if (pTrident->pEnt->location.type == BUS_PCI) { + pTrident->PciInfo = xf86GetPciInfoForEntity(pTrident->pEnt->index); + pTrident->PciTag = pciTag(pTrident->PciInfo->bus, + pTrident->PciInfo->device, + pTrident->PciInfo->func); + pTrident->Linear = TRUE; + } else { + pTrident->Linear = FALSE; + } + } + + if (flags & PROBE_DETECT) { + TRIDENTProbeDDC(pScrn, pTrident->pEnt->index); + return TRUE; + } + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * The first thing we should figure out is the depth, bpp, etc. + * Our default depth is 8, so pass it to the helper function. + * Our preference for depth 24 is 24bpp, so tell it that too. + */ + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb | + SupportConvert32to24 /*| PreferConvert32to24*/)) { + return FALSE; + } else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 1: + case 4: + case 8: + if (pScrn->bitsPerPixel != pScrn->depth) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", + pScrn->depth, pScrn->bitsPerPixel); + return FALSE; + } + break; + case 15: + case 16: + if (pScrn->bitsPerPixel != 16) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", + pScrn->depth, pScrn->bitsPerPixel); + return FALSE; + } + break; + case 24: + if ((pScrn->bitsPerPixel != 24) && (pScrn->bitsPerPixel != 32)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n", + pScrn->depth, pScrn->bitsPerPixel); + return FALSE; + } + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* The vgahw module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + /* + * Allocate a vgaHWRec + */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + vgaIOBase = hwp->IOBase; + pTrident->PIOBase = hwp->PIOOffset; + + xf86SetOperatingState(resVga, pTrident->pEnt->index, ResUnusedOpr); + + /* The ramdac module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "ramdac")) + return FALSE; + + xf86LoaderReqSymLists(ramdacSymbols, NULL); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + return FALSE; + } else { + /* XXX check that weight returned is supported */ + ; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) { + return FALSE; + } else { + /* We don't currently support DirectColor at > 8bpp */ + if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" + " (%s) is not supported at depth %d\n", + xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); + return FALSE; + } + } + + /* + * The new cmap layer needs this to be initialised. + */ + + { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) { + return FALSE; + } + } + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(pTrident->Options = xalloc(sizeof(TRIDENTOptions)))) + return FALSE; + memcpy(pTrident->Options, TRIDENTOptions, sizeof(TRIDENTOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTrident->Options); + + /* Set the bits per RGB for 8bpp mode */ + if (pScrn->depth <= 8) { + /* XXX This is here just to test options. */ + /* Default to 8 */ + pScrn->rgbBits = 6; +#if 0 + if (xf86GetOptValInteger(pTrident->Options, OPTION_RGB_BITS, + &pScrn->rgbBits)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", + pScrn->rgbBits); + } +#endif + } + from = X_DEFAULT; + pTrident->HWCursor = TRUE; + if (xf86ReturnOptValBool(pTrident->Options, OPTION_SW_CURSOR, FALSE)) { + from = X_CONFIG; + pTrident->HWCursor = FALSE; + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOACCEL, FALSE)) { + pTrident->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_PCI_RETRY, FALSE)) { + pTrident->UsePCIRetry = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); + } + pTrident->UsePCIBurst = TRUE; + if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOPCIBURST, FALSE)) { + pTrident->UsePCIBurst = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI Burst disbled\n"); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_1400_DISPLAY, FALSE)) { + pTrident->displaySize = 1400; + } + if(xf86GetOptValInteger(pTrident->Options, OPTION_VIDEO_KEY, + &(pTrident->videoKey))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", + pTrident->videoKey); + } else { + pTrident->videoKey = (1 << pScrn->offset.red) | + (1 << pScrn->offset.green) | + (((pScrn->mask.blue >> pScrn->offset.blue) - 1) + << pScrn->offset.blue); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOMMIO, FALSE)) { + pTrident->NoMMIO = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO Disabled\n"); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_MMIO_ONLY, FALSE)) { + if (pTrident->NoMMIO) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MMIO only cannot be set" + " with NoMMIO\n"); + else { + pTrident->MMIOonly = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO only enabled\n"); + } + } + + pTrident->dspOverride = 0; + if ((s = xf86GetOptValString(pTrident->Options, OPTION_DISPLAY))) { + if(!xf86NameCmp(s, "CRT")) { + pTrident->dspOverride = CRT_ACTIVE; + xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD off CRT on\n"); + } else if (!xf86NameCmp(s, "LCD")) { + pTrident->dspOverride = LCD_ACTIVE; + xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT off\n"); + } else if (!xf86NameCmp(s, "Dual")) { + pTrident->dspOverride = LCD_ACTIVE | CRT_ACTIVE; + xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT on\n"); + } else + xf86DrvMsg(pScrn->scrnIndex,X_ERROR, + "%s is an unknown display option\n",s); + } + if ((s = xf86GetOptValString(pTrident->Options, OPTION_GB))) { + int brightness = -1; + double gamma = -1.0; + Bool error = FALSE; + int i; + + i = sscanf(s,"%lf %i",&gamma,&brightness); + + if (i != 2 || brightness == -1 || gamma == -1.0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Invalid Gamma/Brightness argument: %s\n",s); + error = TRUE; + } else { + if (brightness < 0 || brightness > 128) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "brightness out of range [0,128]: %i\n",brightness); + error = TRUE; + } + if (gamma <= 0.0 || gamma > 10.0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "gamma out of range (0,10.0]: %f\n",gamma); + error = TRUE; + } + } + + if (!error) { + pTrident->GammaBrightnessOn = TRUE; + pTrident->gamma = gamma; + pTrident->brightness = brightness; + xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Gamma: %f Brightness: %i\n", + gamma,brightness); + } + } + + /* The following is a temporary hack */ + pTrident->FPDelay = 7; /* invalid value */ + if (xf86GetOptValInteger(pTrident->Options, OPTION_FP_DELAY, + &pTrident->FPDelay)) { + if (pTrident->FPDelay < -2 || pTrident->FPDelay > 5) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FPDelay %i out if range " + "(-2 < FPDelay < 5)\n",pTrident->FPDelay); + pTrident->FPDelay = 7; + } else + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP Delay set to %i\n", + pTrident->FPDelay); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_SHADOW, FALSE)) { + pTrident->CyberShadow = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Shadow enabled\n"); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_STRETCH, FALSE)) { + pTrident->CyberStretch = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Stretch enabled\n"); + } + + pTrident->MUXThreshold = 90000; /* 90MHz */ + if (xf86GetOptValInteger(pTrident->Options, OPTION_MUX_THRESHOLD, + &pTrident->MUXThreshold)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MUX Threshold set to %d\n", + pTrident->MUXThreshold); + } + pTrident->OverrideHsync = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC, + &pTrident->OverrideHsync)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n", + pTrident->OverrideHsync); + } + pTrident->OverrideVsync = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC, + &pTrident->OverrideVsync)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n", + pTrident->OverrideVsync); + } + pTrident->OverrideHsync = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC, + &pTrident->OverrideHsync)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n", + pTrident->OverrideHsync); + } + pTrident->OverrideVsync = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC, + &pTrident->OverrideVsync)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n", + pTrident->OverrideVsync); + } + pTrident->OverrideRskew = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_RSKEW, + &pTrident->OverrideRskew)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Rskew set to %d\n", + pTrident->OverrideRskew); + } + pTrident->OverrideBskew = 0; + if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_BSKEW, + &pTrident->OverrideBskew)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Bskew set to %d\n", + pTrident->OverrideBskew); + } + if (xf86ReturnOptValBool(pTrident->Options, OPTION_SHADOW_FB, FALSE)) { + if (!pTrident->Linear) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option SHADOW_FB" + " in non-Linear Mode\n"); + else if (pScrn->depth < 8) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Tgnoring Option SHADOW_FB" + " when depth < 8"); + else { + pTrident->ShadowFB = TRUE; + pTrident->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\" - acceleration disabled\n"); + } + } + pTrident->Rotate = 0; + if ((s = xf86GetOptValString(pTrident->Options, OPTION_ROTATE))) { + if (!pTrident->Linear) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option ROTATE " + "in non-Linear Mode\n"); + else if (pScrn->depth < 8) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option ROTATE " + "when depth < 8"); + else { + if(!xf86NameCmp(s, "CW")) { + /* accel is disabled below for shadowFB */ + pTrident->ShadowFB = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + pTrident->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise - acceleration disabled\n"); + } else if(!xf86NameCmp(s, "CCW")) { + pTrident->ShadowFB = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + pTrident->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" + "counter clockwise - acceleration disabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } + } + + /* FIXME ACCELERATION */ + if (!UseMMIO) pTrident->NoAccel = TRUE; + + if (pTrident->Linear) { + if (pTrident->pEnt->device->MemBase != 0) { + /* + * XXX Should check that the config file value matches one of the + * PCI base address values. + */ + pTrident->FbAddress = pTrident->pEnt->device->MemBase; + from = X_CONFIG; + } else { + if (IsPciCard) + pTrident->FbAddress = pTrident->PciInfo->memBase[0]& 0xFFFFFFF0; + else + pTrident->FbAddress = 0xA0000; + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pTrident->FbAddress); + } + + if (UseMMIO) { + if (pTrident->pEnt->device->IOBase != 0) { + /* + * XXX Should check that the config file value matches one of the + * PCI base address values. + */ + pTrident->IOAddress = pTrident->pEnt->device->IOBase; + from = X_CONFIG; + } else { + if (IsPciCard) + pTrident->IOAddress = pTrident->PciInfo->memBase[1]& 0xFFFFC000; + else + /* FIXME - Multihead UNAWARE */ + pTrident->IOAddress = 0xBF000; + } + + xf86DrvMsg(pScrn->scrnIndex,X_PROBED,"IO registers at 0x%lX\n", + pTrident->IOAddress); + } + + /* Register the PCI-assigned resources. */ + if (xf86RegisterResources(pTrident->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); + return FALSE; + } + + /* Initialize VBE if possible + * Don't move this past MMIO enable!! + * PIO access will be blocked + * when MMIO is turned on! + */ + + if (xf86LoadSubModule(pScrn, "vbe")) { + xf86MonPtr pMon; + vbeInfoPtr pVbe; + + xf86LoaderReqSymLists(vbeSymbols, NULL); + pVbe = VBEInit(NULL,pTrident->pEnt->index); + pMon = vbeDoEDID(pVbe, NULL); +#ifdef VBE_INFO + { + VbeInfoBlock* vbeInfoBlockPtr; + if ((vbeInfoBlockPtr = VBEGetVBEInfo(pVbe))) { + pTrident->vbeModes = VBEBuildVbeModeList(pVbe,vbeInfoBlockPtr); + VBEFreeVBEInfo(vbeInfoBlockPtr); + } + } +#endif + vbeFree(pVbe); + if (pMon) { + if (!xf86LoadSubModule(pScrn, "ddc")) { + TRIDENTFreeRec(pScrn); + return FALSE; + } else { + xf86LoaderReqSymLists(ddcSymbols, NULL); + xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon)); + ddcLoaded = TRUE; + } + } + + } + + if (IsPciCard && UseMMIO) { + if (!TRIDENTMapMem(pScrn)) + return FALSE; + + TRIDENTEnableMMIO(pScrn); + } + + OUTB(0x3C4, RevisionID); revision = INB(0x3C5); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Revision is %d\n",revision); + + pScrn->progClock = TRUE; + pTrident->EngineOperation = 0x00; + pTrident->IsCyber = FALSE; + pTrident->HasSGRAM = FALSE; + pTrident->NewClockCode = FALSE; + pTrident->MUX = FALSE; + Support24bpp = FALSE; + + OUTB(vgaIOBase + 4, InterfaceSel); + + switch (pTrident->Chipset) { + case TVGA9000: + case TVGA9000i: + pScrn->progClock = FALSE; + NoClocks = 16; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA9000/9000i"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TVGA9100B: + pScrn->progClock = FALSE; + NoClocks = 8; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA9100B"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TVGA8900B: + pScrn->progClock = FALSE; + NoClocks = 8; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA8900B"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TVGA8900C: + pScrn->progClock = FALSE; + NoClocks = 16; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA8900C"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TVGA8900D: + pScrn->progClock = FALSE; + NoClocks = 16; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA8900D"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TVGA9200CXr: + pScrn->progClock = FALSE; + NoClocks = 16; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA9200CXr"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TGUI9400CXi: + pScrn->progClock = FALSE; + NoClocks = 16; + pTrident->NoMMIO = TRUE; + pTrident->NoAccel = TRUE; + pTrident->HWCursor = FALSE; + chipset = "TVGA9200CXr"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case TGUI9440AGi: + pTrident->ddc1Read = Tridentddc1Read; + pTrident->HWCursor = FALSE; + chipset = "TGUI9440AGi"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + pTrident->frequency = NTSC; + break; + case CYBER9320: + pTrident->ddc1Read = Tridentddc1Read; + chipset = "Cyber9320"; + ramtype = "Standard DRAM"; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + break; + /* Trident didn't update the PCI ID's and so we have to detemine + * which chips are right ! Then override pTrident->Chipset to + * correct values */ + case TGUI9660: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) + ramtype = "Standard DRAM"; + switch (revision) { + case 0x00: + chipset = "TGUI9660"; + pTrident->Chipset = TGUI9660; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + break; + case 0x01: + chipset = "TGUI9680"; + pTrident->Chipset = TGUI9680; + if (pTrident->UsePCIRetry) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n"); + pTrident->UsePCIRetry = FALSE; /* Not Supported */ + break; + case 0x10: + chipset = "ProVidia 9682"; + Support24bpp = TRUE; + pTrident->Chipset = PROVIDIA9682; + break; + case 0x21: + chipset = "ProVidia 9685"; + Support24bpp = TRUE; + pTrident->NewClockCode = TRUE; + pTrident->Chipset = PROVIDIA9685; + break; + case 0x22: + case 0x23: + chipset = "Cyber 9397"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9397; + pTrident->IsCyber = TRUE; + break; + case 0x2a: + chipset = "Cyber 9397/DVD"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9397DVD; + pTrident->IsCyber = TRUE; + break; + case 0x30: + case 0x33: + case 0x34: + case 0x35: + case 0xB3: + chipset = "Cyber 9385"; + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9385; + pTrident->IsCyber = TRUE; + break; + case 0x38: + case 0x3A: + chipset = "Cyber 9385-1"; + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9385; + pTrident->IsCyber = TRUE; + break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + chipset = "Cyber 9382"; + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9382; + pTrident->IsCyber = TRUE; + break; + case 0x4A: + chipset = "Cyber 9388"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->NewClockCode = TRUE; + pTrident->Chipset = CYBER9388; + pTrident->IsCyber = TRUE; + break; + default: + chipset = "Unknown"; + pTrident->Chipset = TGUI9660; + break; + } + break; + case CYBER9388: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "Cyber 9388"; + pTrident->NewClockCode = TRUE; + break; + case CYBER9397: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "Cyber 9397"; + pTrident->NewClockCode = TRUE; + break; + case CYBER9397DVD: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "Cyber 9397/DVD"; + pTrident->NewClockCode = TRUE; + break; + case CYBER9520: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "Cyber 9520"; + pTrident->NewClockCode = TRUE; + break; + case CYBER9525DVD: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "Cyber 9525/DVD"; + pTrident->NewClockCode = TRUE; + break; + case CYBERBLADEE4: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade e4/128"; + pTrident->NewClockCode = TRUE; + break; + case IMAGE975: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + Support24bpp = TRUE; + chipset = "3DImage975"; + pTrident->NewClockCode = TRUE; + break; + case IMAGE985: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x04) + ramtype = "EDO Ram"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + Support24bpp = TRUE; + chipset = "3DImage985"; + pTrident->NewClockCode = TRUE; + break; + case BLADE3D: + pTrident->ddc1Read = Tridentddc1Read; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x08) + ramtype = "SDRAM"; + if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) { + pTrident->HasSGRAM = TRUE; + ramtype = "SGRAM"; + } + Support24bpp = TRUE; + chipset = "Blade3D"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEI7: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + /* pTrident->IsCyber = TRUE; VIA MVP4 integrated Desktop version */ + Support24bpp = TRUE; + chipset = "CyberBlade/i7/VIA MVP4"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEI7D: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade/DSTN/i7"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEI1: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade/i1"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEI1D: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade/DSTN/i1"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEAI1: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade/Ai1"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case CYBERBLADEAI1D: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SDRAM"; + pTrident->IsCyber = TRUE; + Support24bpp = TRUE; + chipset = "CyberBlade/DSTN/Ai1"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + case BLADEXP: /* 0x9910 */ + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SGRAM"; + pTrident->HasSGRAM = TRUE; + Support24bpp = TRUE; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + OUTB(0x3C4, 0x5D); + if (pTrident->PciInfo->subsysVendor != 0x1023) { + chipset = "CyberBladeXP"; + pTrident->IsCyber = TRUE; + } else + if (!(INB(0x3C5) & 0x01)) { + chipset = "BladeXP"; + } else { + CARD8 mem1, mem2; + OUTB(vgaIOBase + 0x04, SPR); + mem1 = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 0x04, 0xC1); + mem2 = INB(vgaIOBase + 5); + if ((mem1 & 0x0e) && (mem2 == 0x11)) { + chipset = "BladeT64"; + } else { + chipset = "BladeT16"; + } + } + break; + case CYBERBLADEXPAI1: + pTrident->ddc1Read = Tridentddc1Read; + ramtype = "SGRAM"; + pTrident->HasSGRAM = TRUE; + pTrident->IsCyber = TRUE; + pTrident->shadowNew = TRUE; + Support24bpp = TRUE; + chipset = "CyberBladeXPAi1"; + pTrident->NewClockCode = TRUE; + pTrident->frequency = NTSC; + break; + } + + if (!pScrn->progClock) { + pScrn->numClocks = NoClocks; + xf86GetClocks(pScrn, NoClocks, TRIDENTClockSelect, + vgaHWProtect, vgaHWBlankScreen, + vgaIOBase + 0x0A, 0x08, 1, 28322); + from = X_PROBED; + xf86ShowClocks(pScrn, from); + } + + if (!chipset) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No support for \"%s\"\n", + pScrn->chipset); + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Found %s chip\n", chipset); + if (ramtype) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RAM type is %s\n", ramtype); + + if (pScrn->bitsPerPixel == 24 && !Support24bpp) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No support for 24bpp on this chipset, use -pixmap32.\n"); + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + return FALSE; + } + + /* HW bpp matches reported bpp */ + pTrident->HwBpp = pScrn->bitsPerPixel; + + /* Due to bugs in the chip, turn it off */ + if (pTrident->Chipset >= CYBERBLADEI7 && pTrident->Chipset <= CYBERBLADEAI1D) + pTrident->HWCursor = FALSE; + + from = X_PROBED; + if (pTrident->pEnt->device->videoRam != 0) { + pScrn->videoRam = pTrident->pEnt->device->videoRam; + from = X_CONFIG; + + /* Due to only 12bits of cursor location, if user has overriden + * disable the cursor automatically */ + if (pTrident->Chipset >= CYBER9397 && pTrident->Chipset < CYBERBLADEE4) + if (pTrident->pEnt->device->videoRam > 4096) + pTrident->HWCursor = FALSE; + } else { + if (pTrident->Chipset == CYBER9525DVD) { + pScrn->videoRam = 2560; + } else + { + OUTB(vgaIOBase + 4, SPR); + videoram = INB(vgaIOBase + 5); + if (pTrident->Chipset < TGUI9440AGi) + videorammask = 0x07; + else + videorammask = 0x0F; + switch (videoram & videorammask) { + case 0x01: + pScrn->videoRam = 512; + break; + case 0x02: /* XP */ + pScrn->videoRam = 6144; + break; + case 0x03: + pScrn->videoRam = 1024; + break; + case 0x04: + /* + * 8MB, but - hw cursor can't store above 4MB + * This only affects Image series chipsets, but for + * some reason, reports suggest that the 9397DVD isn't + * affected. XXX needs furthur investigation ! + */ + if (pTrident->HWCursor && (pTrident->Chipset != CYBER9397DVD) && + (pTrident->Chipset < CYBERBLADEE4)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Found 8MB board, using 4MB\n"); + pScrn->videoRam = 4096; + } else + pScrn->videoRam = 8192; + break; + case 0x06: /* XP */ + pScrn->videoRam = 10240; + break; + case 0x07: + pScrn->videoRam = 2048; + break; + case 0x08: /* XP */ + pScrn->videoRam = 12288; + break; + case 0x0A: /* XP */ + pScrn->videoRam = 14336; + break; + case 0x0C: /* XP */ + pScrn->videoRam = 16384; + break; + case 0x0E: /* XP */ + OUTB(vgaIOBase + 4, 0xC1); + switch (INB(vgaIOBase + 5) & 0x11) { + case 0x00: + pScrn->videoRam = 20480; + break; + case 0x01: + pScrn->videoRam = 24576; + break; + case 0x10: + pScrn->videoRam = 28672; + break; + case 0x11: + pScrn->videoRam = 32768; + break; + } + break; + case 0x0F: + pScrn->videoRam = 4096; + break; + default: + pScrn->videoRam = 1024; + xf86DrvMsg(pScrn->scrnIndex, from, + "Unable to determine VideoRam, defaulting to 1MB\n", + pScrn->videoRam); + break; + } + } + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pTrident->HWCursor ? "HW" : "SW"); + + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", + pScrn->videoRam); + + if (pTrident->IsCyber) { + unsigned char mod, dsp, dsp1; + + pTrident->lcdMode = 0xff; + + OUTB(0x3CE,0x42); + dsp = INB(0x3CF); + OUTB(0x3CE,0x43); + dsp1 = INB(0x3CF); + OUTB(0x3CE,0x52); + mod = INB(0x3CF); + /* + * Only allow display size override if 1280x1024 is detected + * Currently 1400x1050 is supported - which is detected as + * 1280x1024 + */ + if (pTrident->displaySize) { + if (((mod >> 4) & 3) == 0) { + for (i = 0; LCD[i].mode != 0xff; i++) { + if (pTrident->displaySize == LCD[i].display_x) + pTrident->lcdMode = LCD[i].mode; + } + xf86DrvMsg(pScrn->scrnIndex, + X_CONFIG,"%s Panel %ix%i found\n", + (dsp & 0x80) ? "TFT" : + ((dsp1 & 0x20) ? "DSTN" : "STN"), + LCD[i].display_x,LCD[i].display_y); + } else { + xf86DrvMsg(pScrn->scrnIndex,X_WARNING, + "Display size override only for 1280x1024\n"); + pTrident->displaySize = 0; + } + } + + if (!pTrident->displaySize) { + for (i = 0; LCD[i].mode != 0xff; i++) { + if (LCD[i].mode == ((mod >> 4) & 3)) { + pTrident->lcdMode = i; + xf86DrvMsg(pScrn->scrnIndex, + X_PROBED,"%s Panel %ix%i found\n", + (dsp & 0x80) ? "TFT" : + ((dsp1 & 0x20) ? "DSTN" : "STN"), + LCD[i].display_x,LCD[i].display_y); + } + } + } + if (pTrident->dspOverride) { + if (pTrident->dspOverride & LCD_ACTIVE) + pTrident->lcdActive = TRUE; + else + pTrident->lcdActive = FALSE; + } else { + OUTB(0x3CE, FPConfig); + pTrident->lcdActive = (INB(0x3CF) & 0x10); + } + } + + pTrident->MCLK = 0; + mclk = CalculateMCLK(pScrn); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory Clock is %3.2f MHz\n", mclk); + if (xf86GetOptValFreq(pTrident->Options, OPTION_SETMCLK, OPTUNITS_MHZ, + &real)) { + pTrident->MCLK = (int)(real * 1000.0); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting new Memory Clock to %3.2f MHz\n", + (float)(pTrident->MCLK / 1000)); + } + + /* Set the min pixel clock */ + pTrident->MinClock = 12000; /* XXX Guess, need to check this */ + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", + pTrident->MinClock / 1000); + + /* + * If the user has specified ramdac speed in the XF86Config + * file, we respect that setting. + */ + if (pTrident->pEnt->device->dacSpeeds[0]) { + int speed = 0; + + switch (pScrn->bitsPerPixel) { + case 8: + speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + case 32: + speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP32]; + break; + } + if (speed == 0) + pTrident->MaxClock = pTrident->pEnt->device->dacSpeeds[0]; + else + pTrident->MaxClock = speed; + from = X_CONFIG; + } else { + switch (pScrn->bitsPerPixel) { + case 16: + pTrident->MaxClock = ClockLimit16bpp[pTrident->Chipset]; + break; + case 24: + pTrident->MaxClock = ClockLimit24bpp[pTrident->Chipset]; + break; + case 32: + pTrident->MaxClock = ClockLimit32bpp[pTrident->Chipset]; + break; + default: + pTrident->MaxClock = ClockLimit[pTrident->Chipset]; + break; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", + pTrident->MaxClock / 1000); + + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + if (!pScrn->progClock) { + if (pScrn->videoRam < 1024) + clockRanges->ClockMulFactor = 2; + if (pScrn->bitsPerPixel == 16) + clockRanges->ClockMulFactor = 2; + } + clockRanges->minClock = pTrident->MinClock; + clockRanges->maxClock = pTrident->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + + /* + * xf86ValidateModes will check that the mode HTotal and VTotal values + * don't exceed the chipset's limit if pScrn->maxHValue and + * pScrn->maxVValue are set. Since our TRIDENTValidMode() already takes + * care of this, we don't worry about setting them here. + */ + + if ((pScrn->depth < 8) || + (pScrn->bitsPerPixel == 24)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Disabling Engine due to 24bpp or < 8bpp.\n"); + pTrident->NoAccel = TRUE; + } + + /* Select valid modes from those available */ + if (pTrident->NoAccel || Is3Dchip) { + /* + * XXX Assuming min pitch 256, max 4096 + * XXX Assuming min height 128, max 4096 + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 4096, + pScrn->bitsPerPixel, 128, 4096, + pScrn->display->virtualX, + pScrn->display->virtualY, + pTrident->FbMapSize, + LOOKUP_BEST_REFRESH); + } else { + /* + * XXX Assuming min height 128, max 2048 + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + GetAccelPitchValues(pScrn), 0, 0, + pScrn->bitsPerPixel, 128, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, + pTrident->FbMapSize, + LOOKUP_BEST_REFRESH); + } + + if (i == -1) { + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch (pScrn->bitsPerPixel) { + case 1: + pTrident->EngineOperation |= 0x00; + mod = "xf1bpp"; + Sym = "xf1bppScreenInit"; + break; + case 4: + pTrident->EngineOperation |= 0x00; + mod = "xf4bpp"; + Sym = "xf4bppScreenInit"; + break; + case 8: + pTrident->EngineOperation |= 0x00; + mod = "fb"; + break; + case 16: + pTrident->EngineOperation |= 0x01; + mod = "fb"; + break; + case 24: + pTrident->EngineOperation |= 0x03; + mod = "fb"; + break; + case 32: + pTrident->EngineOperation |= 0x02; + mod = "fb"; + break; + } + + if (mod && xf86LoadSubModule(pScrn, mod) == NULL) { + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + if (mod) { + if (Sym) { + xf86LoaderReqSymbols(Sym, NULL); + } else { + xf86LoaderReqSymLists(fbSymbols, NULL); + } + } + + if (!xf86LoadSubModule(pScrn, "i2c")) { + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(i2cSymbols, NULL); + + /* Load shadow if needed */ + if (pTrident->ShadowFB) { + if (!xf86LoadSubModule(pScrn, "shadow")) { + TRIDENTFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + /* Load XAA if needed */ + if (!pTrident->NoAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(xaaSymbols, NULL); + + switch (pScrn->displayWidth * pScrn->bitsPerPixel / 8) { + case 512: + case 8192: + pTrident->EngineOperation |= 0x00; + break; + case 1024: + pTrident->EngineOperation |= 0x04; + break; + case 2048: + pTrident->EngineOperation |= 0x08; + break; + case 4096: + pTrident->EngineOperation |= 0x0C; + break; + } + } + + /* Load DDC if needed */ + /* This gives us DDC1 - we should be able to get DDC2B using i2c */ + + if (! ddcLoaded) + if (!xf86LoadSubModule(pScrn, "ddc")) { + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + TRIDENTFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(ddcSymbols, NULL); + + if (IsPciCard && UseMMIO) { + TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + + + pTrident->FbMapSize = pScrn->videoRam * 1024; + + pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; + + if (pTrident->IsCyber && pTrident->MMIOonly) + pScrn->racIoFlags = 0; + else + pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; + + return TRUE; +} + +/* + * Map the framebuffer and MMIO memory. + */ + +static Bool +TRIDENTMapMem(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + int mapsize = 0x10000; + + if (Is3Dchip) mapsize = 0x20000; + + if (IsPciCard && UseMMIO) + pTrident->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pTrident->PciTag, pTrident->IOAddress, mapsize); + else { + pTrident->IOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO, + pTrident->PciTag, pTrident->IOAddress, 0x1000); + pTrident->IOBase += 0xF00; + } + + if (pTrident->IOBase == NULL) + return FALSE; + + if (pTrident->Linear) { + if (pTrident->FbMapSize != 0) { + pTrident->FbBase = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_FRAMEBUFFER, + pTrident->PciTag, + (unsigned long)pTrident->FbAddress, + pTrident->FbMapSize); + if (pTrident->FbBase == NULL) + return FALSE; + } + } + else + pTrident->FbBase = hwp->Base; + + return TRUE; +} + +/* + * Unmap the framebuffer and MMIO memory. + */ + +static Bool +TRIDENTUnmapMem(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int mapsize = 0x10000; + + if (Is3Dchip) mapsize = 0x20000; + + /* + * Unmap IO registers to virtual address space + */ + if (IsPciCard && UseMMIO) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, mapsize); + else { + pTrident->IOBase -= 0xF00; + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, 0x1000); + } + pTrident->IOBase = NULL; + + if (pTrident->Linear) { + if (pTrident->FbMapSize != 0) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->FbBase, + pTrident->FbMapSize); + pTrident->FbBase = NULL; + } + } + + return TRUE; +} + + +/* + * This function saves the video state. + */ +static void +TRIDENTSave(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident; + vgaRegPtr vgaReg; + TRIDENTRegPtr tridentReg; + + pTrident = TRIDENTPTR(pScrn); + vgaReg = &VGAHWPTR(pScrn)->SavedReg; + tridentReg = &pTrident->SavedReg; + + vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP | + (IsPrimaryCard ? VGA_SR_FONTS : 0)); + + if (pScrn->progClock) + TridentSave(pScrn, tridentReg); + else + TVGASave(pScrn, tridentReg); +} + + +/* + * Initialise a new mode. This is currently still using the old + * "initialise struct, restore/write struct to HW" model. That could + * be changed. + */ + +static Bool +TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTRegPtr tridentReg; + int clock; + + TridentFindClock(pScrn,mode->Clock); + + clock = pTrident->currentClock; + + switch (pTrident->Chipset) { + case TGUI9660: + case TGUI9680: + case PROVIDIA9682: + case PROVIDIA9685: + case IMAGE975: + case IMAGE985: + case BLADE3D: + case CYBERBLADEI7: + case CYBERBLADEI7D: + case CYBERBLADEI1: + case CYBERBLADEI1D: + case CYBERBLADEAI1: + case CYBERBLADEAI1D: + case CYBER9520: + case CYBER9525DVD: + case CYBERBLADEE4: + case CYBER9397: + case CYBER9397DVD: + case BLADEXP: + case CYBERBLADEXPAI1: + /* Get ready for MUX mode */ + if (pTrident->MUX && + pScrn->bitsPerPixel == 8 && + !mode->CrtcHAdjusted) { + mode->CrtcHDisplay >>= 1; + mode->CrtcHSyncStart >>= 1; + mode->CrtcHSyncEnd >>= 1; + mode->CrtcHBlankStart >>= 1; + mode->CrtcHBlankEnd >>= 1; + mode->CrtcHTotal >>= 1; + mode->CrtcHAdjusted = TRUE; + } + break; + default: + if (pScrn->videoRam < 1024 && + !mode->CrtcHAdjusted) { + mode->CrtcHDisplay <<= 1; + mode->CrtcHSyncStart <<= 1; + mode->CrtcHSyncEnd <<= 1; + mode->CrtcHBlankStart <<= 1; + mode->CrtcHBlankEnd <<= 1; + mode->CrtcHTotal <<= 1; + mode->CrtcHAdjusted = TRUE; + } + break; + } + + vgaHWUnlock(hwp); + /* Initialise the ModeReg values */ + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + /* + * We used to do this at a later time. + * Now since READOUT isn't defined any more + * we do it here. + * The original NOTE read: + * TridentInit() has to modify registers + * that have already been set by vgaHWRestore(). + * So we call it _after_ vgaHWRestore() has + * programmed these registers. + */ + if (pScrn->progClock) { + if (!TridentInit(pScrn, mode)) + return FALSE; + } else { + if (!TVGAInit(pScrn, mode)) + return FALSE; + } + + /* Program the registers */ + vgaHWProtect(pScrn, TRUE); + vgaReg = &hwp->ModeReg; + tridentReg = &pTrident->ModeReg; + + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); + if (pScrn->progClock) + TridentRestore(pScrn, tridentReg); + else + TVGARestore(pScrn, tridentReg); + + vgaHWProtect(pScrn, FALSE); + + if (xf86IsPc98()) + PC98TRIDENTEnable(pScrn); + + return TRUE; +} + +/* + * Restore the initial (text) mode. + */ +static void +TRIDENTRestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp; + vgaRegPtr vgaReg; + TRIDENTPtr pTrident; + TRIDENTRegPtr tridentReg; + + hwp = VGAHWPTR(pScrn); + pTrident = TRIDENTPTR(pScrn); + vgaReg = &hwp->SavedReg; + tridentReg = &pTrident->SavedReg; + + vgaHWProtect(pScrn, TRUE); + + if (pScrn->progClock) + TridentRestore(pScrn, tridentReg); + else + TVGARestore(pScrn, tridentReg); + + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP | + (IsPrimaryCard ? VGA_SR_FONTS : 0)); + + vgaHWProtect(pScrn, FALSE); +} + + +/* Mandatory */ + +/* This gets called at the start of each server generation */ + +static Bool +TRIDENTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + /* The vgaHW references will disappear one day */ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + int vgaIOBase; + TRIDENTPtr pTrident; + int ret; + VisualPtr visual; + unsigned char *FBStart; + int width, height, displayWidth; + + /* + * First get the ScrnInfoRec + */ + pScrn = xf86Screens[pScreen->myNum]; + pTrident = TRIDENTPTR(pScrn); + + if (IsPrimaryCard) { + if (!vgaHWMapMem(pScrn)) + return FALSE; + } + + /* Map the TRIDENT memory and MMIO areas */ + if (!TRIDENTMapMem(pScrn)) + return FALSE; + + if (!xf86IsPc98()) { +#ifdef VBE_INFO + if (pTrident->vbeModes) { + pTrident->pVbe = VBEInit(NULL,pTrident->pEnt->index); + pTrident->Int10 = pTrident->pVbe->pInt10; + } else +#endif + { + if (xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols, NULL); + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Initializing int10\n"); + pTrident->Int10 = xf86InitInt10(pTrident->pEnt->index); + } + } + } + + hwp = VGAHWPTR(pScrn); + + if (IsPciCard && UseMMIO) { + TRIDENTEnableMMIO(pScrn); + + /* Initialize the MMIO vgahw functions */ + vgaHWSetMmioFuncs(hwp, pTrident->IOBase, 0); + } + + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* Save the current state */ + TRIDENTSave(pScrn); + + /* + * Some Trident chip on PC-9821 needs setup, + * because VGA chip is not initialized by VGA BIOS. + */ + if (IsPciCard && xf86IsPc98()) { + PC98TRIDENTInit(pScrn); + } else tridentSetModeBIOS(pScrn,pScrn->currentMode); + + /* Initialise the first mode */ + if (!TRIDENTModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + /* Darken the screen for aesthetic reasons and set the viewport */ + TRIDENTSaveScreen(pScreen, SCREEN_SAVER_ON); + TRIDENTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + * For most PC hardware at depths >= 8, the defaults that cfb uses + * are not appropriate. In this driver, we fixup the visuals after. + */ + + /* + * Reset visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) { + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + + miSetPixmapDepths (); + + /* FIXME - we don't do shadowfb for < 4 */ + displayWidth = pScrn->displayWidth; + if (pTrident->Rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } else { + width = pScrn->virtualX; + height = pScrn->virtualY; + } + + if(pTrident->ShadowFB) { + pTrident->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + pTrident->ShadowPtr = xalloc(pTrident->ShadowPitch * height); + displayWidth = pTrident->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FBStart = pTrident->ShadowPtr; + } else { + pTrident->ShadowFB = FALSE; + pTrident->ShadowPtr = NULL; + FBStart = pTrident->FbBase; + } + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + + switch (pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 8: + case 16: + case 24: + case 32: + ret = fbScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth, pScrn->bitsPerPixel); + + break; + default: + xf86DrvMsg(scrnIndex, X_ERROR, + "Internal error: invalid bpp (%d) in TRIDENTScrnInit\n", + pScrn->bitsPerPixel); + ret = FALSE; + break; + } + if (!ret) { + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } else { + if (pScrn->bitsPerPixel == 1) { + TRIDENTFix1bpp(pScrn); + } + } + + /* must be after RGB ordering fixed */ + if (pScrn->bitsPerPixel > 4) + fbPictureInit (pScreen, 0, 0); + + xf86SetBlackWhitePixels(pScreen); + + pTrident->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = TRIDENTBlockHandler; + + if (!pTrident->ShadowFB) + TRIDENTDGAInit(pScreen); + + if (!pTrident->Linear) { + miBankInfoPtr pBankInfo; + + /* Setup the vga banking variables */ + pBankInfo = xnfcalloc(sizeof(miBankInfoRec),1); + if (pBankInfo == NULL) { + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + pBankInfo->pBankA = pTrident->FbBase; + pBankInfo->pBankB = pTrident->FbBase; + pBankInfo->BankSize = 0x10000; + pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth; + + pBankInfo->SetSourceBank = + (miBankProcPtr)TVGA8900SetRead; + pBankInfo->SetDestinationBank = + (miBankProcPtr)TVGA8900SetWrite; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)TVGA8900SetReadWrite; + if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, + pScrn->displayWidth, pBankInfo)) { + xfree(pBankInfo); + pBankInfo = NULL; + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + } + + if (Is3Dchip) { + if ((pTrident->Chipset == CYBERBLADEI7) || + (pTrident->Chipset == CYBERBLADEI7D) || + (pTrident->Chipset == CYBERBLADEI1) || + (pTrident->Chipset == CYBERBLADEI1D) || + (pTrident->Chipset == CYBERBLADEAI1) || + (pTrident->Chipset == CYBERBLADEAI1D) || + (pTrident->Chipset == CYBERBLADEE4) || + (pTrident->Chipset == BLADE3D)) + BladeAccelInit(pScreen); + else + if (pTrident->Chipset >= BLADEXP) + XPAccelInit(pScreen); + else + ImageAccelInit(pScreen); + } else { + TridentAccelInit(pScreen); + } + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + /* Initialise cursor functions */ + miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); + + if (pScrn->bitsPerPixel < 8) + pTrident->HWCursor = FALSE; + + if (pTrident->HWCursor) { + xf86SetSilkenMouse(pScreen); + TridentHWCursorInit(pScreen); + } + + /* Initialise default colourmap */ + if (!miCreateDefColormap(pScreen)) { + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + if(!xf86HandleColormaps(pScreen, 256, 6, TridentLoadPalette, + TridentSetOverscan, CMAP_RELOAD_ON_MODE_SWITCH|CMAP_PALETTED_TRUECOLOR)) { + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + return FALSE; + } + if(pTrident->ShadowFB) { + if(pTrident->Rotate) { + if (!pTrident->PointerMoved) { + pTrident->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = TRIDENTPointerMoved; + } + switch (pScrn->bitsPerPixel) { + case 8: pTrident->RefreshArea = TRIDENTRefreshArea8; break; + case 16: pTrident->RefreshArea = TRIDENTRefreshArea16; break; + case 24: pTrident->RefreshArea = TRIDENTRefreshArea24; break; + case 32: pTrident->RefreshArea = TRIDENTRefreshArea32; break; + } + } else { + pTrident->RefreshArea = TRIDENTRefreshArea; + } + shadowInit (pScreen, TRIDENTShadowUpdate, 0); + } + + xf86DPMSInit(pScreen, (DPMSSetProcPtr)TRIDENTDisplayPowerManagementSet, 0); + + pScrn->memPhysBase = pTrident->FbAddress; + pScrn->fbOffset = 0; + +#ifdef XvExtension + if (pTrident->Chipset >= TGUI9660) + TRIDENTInitVideo(pScreen); +#endif + + pTrident->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = TRIDENTCloseScreen; + pScreen->SaveScreen = TRIDENTSaveScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + +#if 0 + TRIDENTI2CInit(pScreen); + + xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,pTrident->DDC)); +#endif + + return TRUE; +} + +/* Usually mandatory */ +Bool +TRIDENTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return TRIDENTModeInit(xf86Screens[scrnIndex], mode); +} + + +/* + * This function is used to initialize the Start Address - the first + * displayed location in the video memory. + */ +/* Usually mandatory */ +void +TRIDENTAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + TRIDENTPtr pTrident; + vgaHWPtr hwp; + int base = y * pScrn->displayWidth + x; + int vgaIOBase; + CARD8 temp; + + hwp = VGAHWPTR(pScrn); + pTrident = TRIDENTPTR(pScrn); + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + switch (pScrn->bitsPerPixel) { + case 4: + base >>= 3; + break; + case 8: + if (pScrn->progClock) + base = (base & 0xFFFFFFF8) >> 2; + else + base = (base & 0xFFFFFFF8) >> 3; + break; + case 16: + base >>= 1; + break; + case 24: + base = (((base + 1) & ~0x03) * 3) >> 2; + break; + case 32: + break; + } + + /* CRT bits 0-15 */ + OUTW(vgaIOBase + 4, (base & 0x00FF00) | 0x0C); + OUTW(vgaIOBase + 4, ((base & 0x00FF) << 8) | 0x0D); + /* CRT bit 16 */ + OUTB(vgaIOBase + 4, CRTCModuleTest); temp = INB(vgaIOBase + 5) & 0xDF; + OUTB(vgaIOBase + 5, temp | ((base & 0x10000) >> 11)); + /* CRT bit 17-19 */ + OUTB(vgaIOBase + 4, CRTHiOrd); temp = INB(vgaIOBase + 5) & 0xF8; + OUTB(vgaIOBase + 5, temp | ((base & 0xE0000) >> 17)); +} + + +/* + * This is called when VT switching back to the X server. Its job is + * to reinitialise the video mode. + */ + +/* Mandatory */ +static Bool +TRIDENTEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn); + + /* Should we re-save the text mode on each VT enter? */ + if (!TRIDENTModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + if (pTrident->InitializeAccelerator) + pTrident->InitializeAccelerator(pScrn); + + return TRUE; +} + + +/* + * This is called when VT switching away from the X server. Its job is + * to restore the previous (text) mode. + * + * We may wish to remap video/MMIO memory too. + */ + +/* Mandatory */ +static void +TRIDENTLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + TRIDENTRestore(pScrn); + vgaHWLock(hwp); + + if (xf86IsPc98()) + PC98TRIDENTDisable(pScrn); + + if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); +} + + +/* + * This is called at the end of each server generation. It restores the + * original (text) mode. It should really also unmap the video memory too. + */ + +/* Mandatory */ +static Bool +TRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (xf86IsPc98()) + PC98TRIDENTDisable(pScrn); + + if (pScrn->vtSema) { + TRIDENTRestore(pScrn); + vgaHWLock(hwp); + if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn); + TRIDENTUnmapMem(pScrn); + } + if (pTrident->AccelInfoRec) + XAADestroyInfoRec(pTrident->AccelInfoRec); + if (pTrident->CursorInfoRec) + xf86DestroyCursorInfoRec(pTrident->CursorInfoRec); + if (pTrident->ShadowPtr) + xfree(pTrident->ShadowPtr); + if (pTrident->DGAModes) + xfree(pTrident->DGAModes); + pScrn->vtSema = FALSE; + + if(pTrident->BlockHandler) + pScreen->BlockHandler = pTrident->BlockHandler; + + if (pTrident->pVbe) + vbeFree(pTrident->pVbe); + else + xf86FreeInt10(pTrident->Int10); + pScreen->CloseScreen = pTrident->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +/* Free up any per-generation data structures */ + +/* Optional */ +static void +TRIDENTFreeScreen(int scrnIndex, int flags) +{ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + TRIDENTFreeRec(xf86Screens[scrnIndex]); +} + + +/* Checks if a mode is suitable for the selected chipset. */ + +/* Optional */ +static int +TRIDENTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (pTrident->lcdActive && (pTrident->lcdMode != 0xff)){ + if (((mode->HDisplay > LCD[pTrident->lcdMode].display_x) + || (mode->VDisplay > LCD[pTrident->lcdMode].display_y))) { + xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) " + "larger than the LCD panel (%dx%d)\n", + mode->HDisplay, + mode->VDisplay, + LCD[pTrident->lcdMode].display_x, + LCD[pTrident->lcdMode].display_y); + return(MODE_BAD); + } + if (((float)mode->HDisplay/(float)mode->VDisplay) > 2.0) { + xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) " + "unusual aspect ratio\n", + mode->HDisplay, + mode->VDisplay); + return(MODE_BAD); + } + } + return (MODE_OK); +} + +/* Do screen blanking */ + +/* Mandatory */ +static Bool +TRIDENTSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + +static void +TRIDENTEnableMMIO(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + IOADDRESS vgaIOBase = pTrident->PIOBase + VGAHWPTR(pScrn)->IOBase; + CARD8 temp = 0, protect = 0; + + /* + * Skip MMIO Enable in PC-9821 PCI Trident Card!! + * Because of lack of non PCI VGA port + */ + if (IsPciCard && xf86IsPc98()) + return; + + /* Goto New Mode */ + outb(pTrident->PIOBase + 0x3C4, 0x0B); + inb(pTrident->PIOBase + 0x3C5); + + /* Unprotect registers */ + if (pTrident->Chipset > PROVIDIA9685) { + outb(pTrident->PIOBase + 0x3C4, Protection); + protect = inb(pTrident->PIOBase + 0x3C5); + outb(pTrident->PIOBase + 0x3C5, 0x92); + } + outb(pTrident->PIOBase + 0x3C4, NewMode1); + temp = inb(pTrident->PIOBase + 0x3C5); + outb(pTrident->PIOBase + 0x3C5, 0x80); + + /* Enable MMIO */ + outb(vgaIOBase + 4, PCIReg); + pTrident->REGPCIReg = inb(vgaIOBase + 5); + outb(vgaIOBase + 5, pTrident->REGPCIReg | 0x01); /* Enable it */ + + /* Protect registers */ + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, protect); + } + OUTB(0x3C4, NewMode1); + OUTB(0x3C5, temp); +} + +static void +TRIDENTDisableMMIO(ScrnInfoPtr pScrn) +{ + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + CARD8 temp = 0, protect = 0; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + /* + * Skip MMIO Disable in PC-9821 PCI Trident Card!! + * Because of lack of non PCI VGA port + */ + if (IsPciCard && xf86IsPc98()) + return; + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); temp = INB(0x3C5); + + /* Unprotect registers */ + OUTB(0x3C4, NewMode1); temp = INB(0x3C5); + OUTB(0x3C5, 0x80); + if (pTrident->Chipset > PROVIDIA9685) { + OUTB(0x3C4, Protection); + protect = INB(0x3C5); + OUTB(0x3C5, 0x92); + } + + /* Disable MMIO access */ + OUTB(vgaIOBase + 4, PCIReg); + pTrident->REGPCIReg = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 5, pTrident->REGPCIReg & 0xFE); + + /* Protect registers */ + if (pTrident->Chipset > PROVIDIA9685) { + outb(pTrident->PIOBase + 0x3C4, Protection); + outb(pTrident->PIOBase + 0x3C5, protect); + } + outb(pTrident->PIOBase + 0x3C4, NewMode1); + outb(pTrident->PIOBase + 0x3C5, temp); +} + +/* Initialize VGA Block for Trident Chip on PC-98x1 */ +static void +PC98TRIDENTInit(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + switch (pTrident->Chipset) { + case TGUI9660: + case TGUI9680: + case PROVIDIA9682: + PC98TRIDENT96xxInit(pScrn); + break; + case CYBER9320: + case CYBER9385: + PC98TRIDENT9385Init(pScrn); + break; + default: /* Run 96xx code as default */ + PC98TRIDENT96xxInit(pScrn); + break; + } +} + +static void +PC98TRIDENTEnable(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + switch (pTrident->Chipset) { + case TGUI9660: + case TGUI9680: + case PROVIDIA9682: + PC98TRIDENT96xxEnable(pScrn); + break; + case CYBER9320: + case CYBER9385: + PC98TRIDENT9385Enable(pScrn); + break; + default: /* Run 96xx code as default */ + PC98TRIDENT96xxEnable(pScrn); + break; + } +} + +static void +PC98TRIDENTDisable(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + switch (pTrident->Chipset) { + case TGUI9660: + case TGUI9680: + case PROVIDIA9682: + PC98TRIDENT96xxDisable(pScrn); + break; + case CYBER9320: + case CYBER9385: + PC98TRIDENT9385Disable(pScrn); + break; + default: /* Run 96xx code as default */ + PC98TRIDENT96xxDisable(pScrn); + break; + } +} + +/* Initialize VGA Block for Cyber9385 on PC-98x1 */ +static void +PC98TRIDENT9385Init(ScrnInfoPtr pScrn) +{ +/* Nothing to initialize */ +} + +static void +PC98TRIDENT9385Enable(ScrnInfoPtr pScrn) +{ + outb(0xFAC, 0x02); +} + +static void +PC98TRIDENT9385Disable(ScrnInfoPtr pScrn) +{ + outb(0xFAC, 0x00); +} + +/* Initialize VGA Block for Trident96xx on PC-98x1 */ +static void +PC98TRIDENT96xxInit(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + CARD8 temp = 0; + + vgaHWProtect(pScrn, TRUE); + + /* Video SusSystem Enable */ + temp = INB(0x3CC); + OUTB(0x3C2, temp | 0xC3); + /* Switch Old */ + OUTB(0x3C4, 0x0B); temp = INB(0x3C5); + OUTW(0x3C4, 0x0B | (temp << 8)); + /* Select Configuration Port 1 */ + OUTB(0x3C4, 0x0E); temp = INB(0x3C5); + OUTW(0x3C4, 0x0E | ((temp | 0x20) << 8)); + + OUTB(0x3C4, 0x0c); + if((INB(0x3C5) & 0x10) == 0x10) + { + OUTB(0x3C4, 0x0E | (temp << 8)); + OUTB(0x94, 0x00); + OUTB(0x102, 0x01); + OUTB(0x94, 0x20); + temp = INB(0x3C3); + OUTB(0x3C3, temp | 0x01); + } else { + OUTB(0x3C4, 0x0E | (temp << 8)); + OUTB(0x46E8, 0x10); + OUTB(0x102, 0x01); + OUTB(0x46E8, 0x08); + } + + INB(0x3DA); + OUTB(0x3C0,0x10); + OUTB(0x3C0,0x41); + + /* Register Unlock */ + vgaHWUnlock(hwp); + OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */ + OUTB(0x3C4, 0x0E); temp = INB(0x3C5); + OUTW(0x3C4, 0x0E | ((temp | 0x80) << 8)); + + /* For Speed Up [Facoor 2 at Xengine] */ + OUTW(0x3D4, 0x3820); /* Command FIFO Register */ + OUTW(0x3D4, 0x2020); /* Command FIFO Register */ + /* Latency Control Registers 0x30 - 0x32 */ + /* Parameter Range 0x00 - 0x0F */ + /* Tune these parameter to avoid GE Timeout */ + OUTW(0x3D4, 0x0E30); /* Display Queue Latency Control */ + /* 8bpp GE No Timeout Parameter 0x0D - 0x0F for PC-9821Xa7 TGUi9680 */ + OUTW(0x3D4, 0x0031); /* Frame Buffer Latency Control */ + OUTW(0x3D4, 0x0032); /* Display & Frame Buffer Latency Control */ + OUTW(0x3D4, 0x213B); /* Clock and Tuning */ + + /* MCLK Init */ + OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */ +#if 0 + /* Sample MCLKs */ + OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */ + OUTB(0x43C6, 0xA7); OUTB(0x43C7, 0x00); /* 77.0MHz */ + OUTB(0x43C6, 0x8E); OUTB(0x43C7, 0x00); /* 75.0MHz */ + OUTB(0x43C6, 0x86); OUTB(0x43C7, 0x00); /* 72.0MHz */ + OUTB(0x43C6, 0x8F); OUTB(0x43C7, 0x00); /* 67.2MHz */ + OUTB(0x43C6, 0xD5); OUTB(0x43C7, 0x02); /* 61.6MHz */ +#endif + + /* Register Lock */ + OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */ + OUTB(0x3C4, 0x0E); temp = INB(0x3C5); + OUTW(0x3C4, 0x0E | ((temp & 0x7F) << 8)); + vgaHWLock(hwp); + + vgaHWProtect(pScrn, FALSE); +} + +static void +PC98TRIDENT96xxEnable(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp = 0; + + outb(0x68, 0x0E); + outb(0x6A, 0x07); + outb(0x6A, 0x8F); + outb(0x6A, 0x06); + + vgaHWProtect(pScrn, TRUE); + + OUTB(0x3D4, 0x23); temp = INB(0x3D5); + OUTW(0x3D4, 0x23 | ((temp & 0xDF) << 8)); + + OUTB(0x3D4, 0x29); temp = INB(0x3D5); + OUTW(0x3D4, 0x29 | ((temp | 0x04) << 8)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x06)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x08)); + + OUTB(0x3CE, 0x23); temp = INB(0x3CF); + OUTW(0x3CE, 0x23 | ((temp & 0xFC) << 8)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x01)); + + OUTB(0x3C4, 0x01); temp = INB(0x3C5); + OUTW(0x3C4, 0x01 | ((temp & 0xEF) << 8)); + + vgaHWProtect(pScrn, FALSE); + + outb(0xFAC, 0x02); +} + +static void +PC98TRIDENT96xxDisable(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp = 0; + + outb(0xFAC, 0x00); + + vgaHWProtect(pScrn, TRUE); + + OUTB(0x3C4, 0x01); temp = INB(0x3C5); + OUTW(0x3C4, 0x01 | ((temp | 0x10) << 8)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFE)); + + OUTB(0x3CE, 0x23); temp = INB(0x3CF); + OUTW(0x3CE, 0x23 | (((temp & 0xFC) | 0x01) << 8)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFD)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xCF)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xF7)); + + OUTB(0x83C8, 0x04); temp = INB(0x83c6); + OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFB)); + + OUTB(0x3D4, 0x29); temp = INB(0x3D5); + OUTW(0x3D4, 0x29 | ((temp & 0xFB) << 8)); + + OUTB(0x3D4, 0x23); temp = INB(0x3D5); + OUTW(0x3D4, 0x23 | ((temp | 0x20) << 8)); + + vgaHWProtect(pScrn, FALSE); + + outb(0x6A, 0x07); + outb(0x6A, 0x8E); + outb(0x6A, 0x06); + outb(0x68, 0x0F); +} + + +/* + * This is a terrible hack! If we are on a notebook in a stretched + * mode and don't want full screen we use the BIOS to set an unstreched + * mode. + */ +void +tridentSetModeBIOS(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + +#ifdef VBE_INFO + if (pTrident->vbeModes) { + vbeSaveRestoreRec vbesr; + vbesr.stateMode = VBECalcVbeModeIndex(pTrident->vbeModes, + mode, pScrn->bitsPerPixel); + vbesr.pstate = NULL; + if (vbesr.stateMode) { + if (IsPciCard && UseMMIO) + TRIDENTDisableMMIO(pScrn); + VBEVesaSaveRestore(pTrident->pVbe,&vbesr,MODE_RESTORE); + if (IsPciCard && UseMMIO) + TRIDENTEnableMMIO(pScrn); + return; + } else + xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"No BIOS Mode matches " + "%ix%I@%ibpp\n",mode->HDisplay,mode->VDisplay, + pScrn->bitsPerPixel); + } +#endif + /* This function is only for LCD screens, and also when we have + * int10 available */ + + if (pTrident->IsCyber && pTrident->lcdMode && pTrident->Int10) { + int i = pTrident->lcdMode; + if ((pScrn->currentMode->HDisplay != LCD[i].display_x) /* !fullsize? */ + || (pScrn->currentMode->VDisplay != LCD[i].display_y)) { + if (pTrident->lcdActive) { /* LCD Active ?*/ + int h_str, v_str; + + OUTB(0x3CE,HorStretch); h_str = INB(0x3CF) & 0x01; + OUTB(0x3CE,VertStretch); v_str = INB(0x3CF) & 0x01; + if (h_str || v_str) { + OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92); + OUTW(0x3CE, BiosReg ); + pTrident->Int10->ax = 0x3; + pTrident->Int10->num = 0x10; + if (IsPciCard && UseMMIO) + TRIDENTDisableMMIO(pScrn); + xf86ExecX86int10(pTrident->Int10); + if (IsPciCard && UseMMIO) + TRIDENTEnableMMIO(pScrn); + } + } + } + } +} + diff --git a/src/trident_i2c.c b/src/trident_i2c.c new file mode 100644 index 0000000..1fd23ad --- /dev/null +++ b/src/trident_i2c.c @@ -0,0 +1,77 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_i2c.c,v 1.5 1999/10/13 20:02:30 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "compiler.h" + +#include "xf86Pci.h" +#include "xf86PciInfo.h" + +#include "vgaHW.h" + +#include "trident.h" +#include "trident_regs.h" + +static void +TRIDENTI2CPutBits(I2CBusPtr b, int clock, int data) { + unsigned int reg = 0x0C; + TRIDENTPtr pTrident = ((TRIDENTPtr)b->DriverPrivate.ptr); + int vgaIOBase = VGAHWPTR(pTrident->pScrn)->IOBase; + +#if 0 + if(!TRIDENTI2CSwitchToBus(b)) + return FALSE; +#endif + + if(clock) reg |= 2; + if(data) reg |= 1; + OUTB(vgaIOBase + 4, I2C); + OUTB(vgaIOBase + 5, reg); +#if 0 + ErrorF("TRIDENTI2CPutBits: %d %d\n", clock, data); +#endif +} + +static void +TRIDENTI2CGetBits(I2CBusPtr b, int *clock, int *data) { + unsigned int reg; + TRIDENTPtr pTrident = ((TRIDENTPtr)b->DriverPrivate.ptr); + int vgaIOBase = VGAHWPTR(pTrident->pScrn)->IOBase; + +#if 0 + if(!TRIDENTI2CSwitchToBus(b)) + return FALSE; +#endif + + OUTB(vgaIOBase + 4, I2C); + reg = INB(vgaIOBase + 5); + *clock = (reg & 0x02) != 0; + *data = (reg & 0x01) != 0; +#if 0 + ErrorF("TRIDENTI2CGetBits: %d %d\n", *clock, *data); +#endif +} + +Bool +TRIDENTI2CInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + I2CBusPtr I2CPtr; + + I2CPtr = xf86CreateI2CBusRec(); + + pTrident->DDC = I2CPtr; + + I2CPtr->BusName = "DDC"; + I2CPtr->scrnIndex = pScrn->scrnIndex; + I2CPtr->I2CPutBits = TRIDENTI2CPutBits; + I2CPtr->I2CGetBits = TRIDENTI2CGetBits; + I2CPtr->DriverPrivate.ptr = pTrident; + + if(!xf86I2CBusInit(I2CPtr)) + return FALSE; + + return TRUE; +} diff --git a/src/trident_regs.h b/src/trident_regs.h new file mode 100644 index 0000000..3cce902 --- /dev/null +++ b/src/trident_regs.h @@ -0,0 +1,395 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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_regs.h,v 1.26 2002/09/16 18:06:03 eich Exp $ */ + +#define DEBUG 1 + +#define NTSC 14.31818 +#define PAL 17.73448 + +/* General Registers */ +#define SPR 0x1F /* Software Programming Register (videoram) */ + +/* 3C4 */ +#define RevisionID 0x09 +#define ConfPort1 0x0C +#define ConfPort2 0x0C +#define NewMode2 0x0D +#define OldMode2 0x00 /* Should be 0x0D - dealt with in trident_dac.c */ +#define OldMode1 0x0E +#define NewMode1 0x0E +#define Protection 0x11 +#define Threshold 0x12 +#define MCLKLow 0x16 +#define MCLKHigh 0x17 +#define ClockLow 0x18 +#define ClockHigh 0x19 +#define SSetup 0x20 +#define SKey 0x37 +#define SPKey 0x57 +#define GBslope1 0xB4 +#define GBslope2 0xB5 +#define GBslope3 0xB6 +#define GBslope4 0xB7 +#define GBintercept1 0xB8 +#define GBintercept2 0xB9 +#define GBintercept3 0xBA +#define GBintercept4 0xBB + +/* 3x4 */ +#define Offset 0x13 +#define Underline 0x14 +#define CRTCMode 0x17 +#define CRTCModuleTest 0x1E +#define FIFOControl 0x20 +#define LinearAddReg 0x21 +#define DRAMTiming 0x23 +#define New32 0x23 +#define RAMDACTiming 0x25 +#define CRTHiOrd 0x27 +#define AddColReg 0x29 +#define InterfaceSel 0x2A +#define HorizOverflow 0x2B +#define GETest 0x2D +#define Performance 0x2F +#define GraphEngReg 0x36 +#define I2C 0x37 +#define PixelBusReg 0x38 +#define PCIReg 0x39 +#define DRAMControl 0x3A +#define MiscContReg 0x3C +#define CursorXLow 0x40 +#define CursorXHigh 0x41 +#define CursorYLow 0x42 +#define CursorYHigh 0x43 +#define CursorLocLow 0x44 +#define CursorLocHigh 0x45 +#define CursorXOffset 0x46 +#define CursorYOffset 0x47 +#define CursorFG1 0x48 +#define CursorFG2 0x49 +#define CursorFG3 0x4A +#define CursorFG4 0x4B +#define CursorBG1 0x4C +#define CursorBG2 0x4D +#define CursorBG3 0x4E +#define CursorBG4 0x4F +#define CursorControl 0x50 +#define PCIRetry 0x55 +#define PreEndControl 0x56 +#define PreEndFetch 0x57 +#define PCIMaster 0x60 +#define Enhancement0 0x62 +#define NewEDO 0x64 +#define TVinterface 0xC0 +#define TVMode 0xC1 +#define ClockControl 0xCF + + +/* 3CE */ +#define MiscExtFunc 0x0F +#define MiscIntContReg 0x2F +#define CyberControl 0x30 +#define CyberEnhance 0x31 +#define FPConfig 0x33 +#define VertStretch 0x52 +#define HorStretch 0x53 +#define BiosMode 0x5c +#define BiosNewMode1 0x5a +#define BiosNewMode2 0x5c +#define BiosReg 0x5d + +/* Graphics Engine for 9420/9430 */ + +#define GER_INDEX 0x210A +#define GER_BYTE0 0x210C +#define GER_BYTE1 0x210D +#define GER_BYTE2 0x210E +#define GER_BYTE3 0x210F +#define MMIOBASE 0x7C +#define OLDGER_STATUS 0x90 +#define OLDGER_MWIDTH 0xB8 +#define OLDGER_MFORMAT 0xBC +#define OLDGER_STYLE 0xC4 +#define OLDGER_FMIX 0xC8 +#define OLDGER_BMIX 0xC8 +#define OLDGER_FCOLOUR 0xD8 +#define OLDGER_BCOLOUR 0xDC +#define OLDGER_DIMXY 0xE0 +#define OLDGER_DESTLINEAR 0xE4 +#define OLDGER_DESTXY 0xF8 +#define OLDGER_COMMAND 0xFC +#define OLDGE_FILL 0x000A0000 /* Area Fill */ + +/* Graphics Engine for 9440/9660/9680 */ + +#define GER_STATUS 0x2120 +#define GE_BUSY 0x80 +#define GER_OPERMODE 0x2122 /* Byte for 9440, Word for 96xx */ +#define DST_ENABLE 0x200 /* Destination Transparency */ +#define GER_COMMAND 0x2124 +#define GE_NOP 0x00 /* No Operation */ +#define GE_BLT 0x01 /* BitBLT ROP3 only */ +#define GE_BLT_ROP4 0x02 /* BitBLT ROP4 (96xx only) */ +#define GE_SCANLINE 0x03 /* Scan Line */ +#define GE_BRESLINE 0x04 /* Bresenham Line */ +#define GE_SHVECTOR 0x05 /* Short Vector */ +#define GE_FASTLINE 0x06 /* Fast Line (96xx only) */ +#define GE_TRAPEZ 0x07 /* Trapezoidal fill (96xx only) */ +#define GE_ELLIPSE 0x08 /* Ellipse (96xx only) (RES) */ +#define GE_ELLIP_FILL 0x09 /* Ellipse Fill (96xx only) (RES)*/ +#define GER_FMIX 0x2127 +#define GER_DRAWFLAG 0x2128 /* long */ +#define FASTMODE 1<<28 +#define STENCIL 0x8000 +#define SOLIDFILL 0x4000 +#define TRANS_ENABLE 0x1000 +#define TRANS_REVERSE 0x2000 +#define YMAJ 0x0400 +#define XNEG 0x0200 +#define YNEG 0x0100 +#define SRCMONO 0x0040 +#define PATMONO 0x0020 +#define SCR2SCR 0x0004 +#define PAT2SCR 0x0002 +#define GER_FCOLOUR 0x212C /* Word for 9440, long for 96xx */ +#define GER_BCOLOUR 0x2130 /* Word for 9440, long for 96xx */ +#define GER_PATLOC 0x2134 /* Word */ +#define GER_DEST_XY 0x2138 +#define GER_DEST_X 0x2138 /* Word */ +#define GER_DEST_Y 0x213A /* Word */ +#define GER_SRC_XY 0x213C +#define GER_SRC_X 0x213C /* Word */ +#define GER_SRC_Y 0x213E /* Word */ +#define GER_DIM_XY 0x2140 +#define GER_DIM_X 0x2140 /* Word */ +#define GER_DIM_Y 0x2142 /* Word */ +#define GER_STYLE 0x2144 /* Long */ +#define GER_CKEY 0x2168 /* Long */ +#define GER_FPATCOL 0x2178 +#define GER_BPATCOL 0x217C +#define GER_PATTERN 0x2180 /* from 0x2180 to 0x21FF */ + +/* Additional - Graphics Engine for 96xx */ +#define GER_SRCCLIP_XY 0x2148 +#define GER_SRCCLIP_X 0x2148 /* Word */ +#define GER_SRCCLIP_Y 0x214A /* Word */ +#define GER_DSTCLIP_XY 0x214C +#define GER_DSTCLIP_X 0x214C /* Word */ +#define GER_DSTCLIP_Y 0x214E /* Word */ + +/* Defines for IMAGE Graphics Engine */ +#define IMAGE_GE_STATUS 0x2164 +#define IMAGE_GE_DRAWENV 0x2120 + +/* Defines for BLADE Graphics Engine */ +#define BLADE_GE_STATUS 0x2120 +#define BLADE_XP_GER_OPERMODE 0x2125 + +#define REPLICATE(r) \ +{ \ + if (pScrn->bitsPerPixel == 16) { \ + r = ((r & 0xFFFF) << 16) | (r & 0xFFFF); \ + } else \ + if (pScrn->bitsPerPixel == 8) { \ + r &= 0xFF; \ + r |= (r<<8); \ + r |= (r<<16); \ + } \ +} + +#define CHECKCLIPPING \ + if (pTrident->Clipping) { \ + pTrident->Clipping = FALSE; \ + if (pTrident->Chipset < PROVIDIA9682) { \ + TGUI_SRCCLIP_XY(0,0); \ + TGUI_DSTCLIP_XY(4095,2047); \ + } \ + } + + +/* Merge XY */ +#define XY_MERGE(x,y) \ + ((((CARD32)(y)&0xFFFF) << 16) | ((CARD32)(x) & 0xffff)) +#define XP_XY_MERGE(y,x) \ + ((((CARD32)(y)&0xFFFF) << 16) | ((CARD32)(x) & 0xffff)) + +#define TRIDENT_WRITE_REG(v,r) \ + MMIO_OUT32(pTrident->IOBase,(r),(v)) + +#define TRIDENT_READ_REG(r) \ + MMIO_IN32(pTrident->IOBase,(r)) + +#define OUTB(addr, data) \ +{ \ + if (IsPciCard && UseMMIO) { \ + MMIO_OUT8(pTrident->IOBase, addr, data); \ + } else { \ + outb(pTrident->PIOBase + (addr), data); \ + } \ +} +#define OUTW(addr, data) \ +{ \ + if (IsPciCard && UseMMIO) { \ + MMIO_OUT16(pTrident->IOBase, addr, data); \ + } else { \ + outw(pTrident->PIOBase + (addr), data); \ + } \ +} +#define INB(addr) \ +( \ + (IsPciCard && UseMMIO) ? \ + MMIO_IN8(pTrident->IOBase, addr) : \ + inb(pTrident->PIOBase + (addr)) \ +) + +#define OUTW_3C4(reg) \ + OUTW(0x3C4, (tridentReg->tridentRegs3C4[reg])<<8 | (reg)) +#define OUTW_3CE(reg) \ + OUTW(0x3CE, (tridentReg->tridentRegs3CE[reg])<<8 | (reg)) +#define OUTW_3x4(reg) \ + OUTW(vgaIOBase + 4, (tridentReg->tridentRegs3x4[reg])<<8 | (reg)) +#define INB_3x4(reg) \ + OUTB(vgaIOBase + 4, reg); \ + tridentReg->tridentRegs3x4[reg] = INB(vgaIOBase + 5) +#define INB_3C4(reg) \ + OUTB(0x3C4, reg); \ + tridentReg->tridentRegs3C4[reg] = INB(0x3C5); +#define INB_3CE(reg) \ + OUTB(0x3CE, reg); \ + tridentReg->tridentRegs3CE[reg] = INB(0x3CF); + +#define VIDEOOUT(val,reg) \ + if (pTrident->Chipset >= CYBER9397) { \ + OUTW(0x3C4, (val << 8) | reg); \ + } else { \ + OUTB(0x83C8, reg); \ + OUTB(0x83C6, val); \ + } + + +#define BLTBUSY(b) \ + (b = MMIO_IN8(pTrident->IOBase,GER_STATUS) & GE_BUSY) +#define OLDBLTBUSY(b) \ + (b = MMIO_IN8(pTrident->IOBase,OLDGER_STATUS) & GE_BUSY) +#define IMAGE_STATUS(c) \ + MMIO_OUT32(pTrident->IOBase, IMAGE_GE_STATUS, (c)) +#define TGUI_STATUS(c) \ + MMIO_OUT8(pTrident->IOBase, GER_STATUS, (c)) +#define OLDTGUI_STATUS(c) \ + MMIO_OUT8(pTrident->IOBase, OLDGER_STATUS, (c)) +#define TGUI_OPERMODE(c) \ + MMIO_OUT16(pTrident->IOBase, GER_OPERMODE, (c)) +#define BLADE_XP_OPERMODE(c) \ + MMIO_OUT8(pTrident->IOBase, BLADE_XP_GER_OPERMODE, (c)) +/* XXX */ +#define OLDTGUI_OPERMODE(c) \ + { \ + MMIO_OUT16(pTrident->IOBase, OLDGER_MWIDTH, \ + vga256InfoRec.displayWidth - 1); \ + MMIO_OUT8(pTrident->IOBase, OLDGER_MFORMAT, (c)); \ + } +#define TGUI_FCOLOUR(c) \ + MMIO_OUT32(pTrident->IOBase, GER_FCOLOUR, (c)) +#define TGUI_FPATCOL(c) \ + MMIO_OUT32(pTrident->IOBase, GER_FPATCOL, (c)) +#define OLDTGUI_FCOLOUR(c) \ + MMIO_OUT32(pTrident->IOBase, OLDGER_FCOLOUR, (c)) +#define TGUI_BCOLOUR(c) \ + MMIO_OUT32(pTrident->IOBase, GER_BCOLOUR, (c)) +#define TGUI_BPATCOL(c) \ + MMIO_OUT32(pTrident->IOBase, GER_BPATCOL, (c)) +#define OLDTGUI_BCOLOUR(c) \ + MMIO_OUT32(pTrident->IOBase, OLDGER_BCOLOUR, (c)) +#define IMAGE_DRAWENV(c) \ + MMIO_OUT32(pTrident->IOBase, IMAGE_GE_DRAWENV, (c)) +#define TGUI_DRAWFLAG(c) \ + MMIO_OUT32(pTrident->IOBase, GER_DRAWFLAG, (c)) +#define OLDTGUI_STYLE(c) \ + MMIO_OUT16(pTrident->IOBase, OLDGER_STYLE, (c)) +#define TGUI_FMIX(c) \ + MMIO_OUT8(pTrident->IOBase, GER_FMIX, (c)) +#define OLDTGUI_FMIX(c) \ + MMIO_OUT8(pTrident->IOBase, OLDGER_FMIX, (c)) +#define OLDTGUI_BMIX(c) \ + MMIO_OUT8(pTrident->IOBase, OLDGER_BMIX, (c)) +#define TGUI_DIM_XY(w,h) \ + MMIO_OUT32(pTrident->IOBase, GER_DIM_XY, XY_MERGE((w)-1,(h)-1)) +#define XP_DIM_XY(w,h) \ + MMIO_OUT32(pTrident->IOBase, GER_DIM_XY, XY_MERGE((h),(w))) +#define TGUI_STYLE(c) \ + MMIO_OUT32(pTrident->IOBase, GER_STYLE, (c)) +#define OLDTGUI_DIMXY(w,h) \ + MMIO_OUT32(pTrident->IOBase, OLDGER_DIMXY, XY_MERGE((w)-1,(h)-1)) +#define TGUI_SRC_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_SRC_XY, XY_MERGE(x,y)) +#define XP_SRC_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_SRC_XY, XP_XY_MERGE(x,y)) +#define TGUI_DEST_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_DEST_XY, XY_MERGE(x,y)) +#define XP_DEST_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_DEST_XY, XP_XY_MERGE(x,y)) +#define OLDTGUI_DESTXY(x,y) \ + MMIO_OUT32(pTrident->IOBase, OLDGER_DESTXY, XY_MERGE(x,y)) +#define OLDTGUI_DESTLINEAR(c) \ + MMIO_OUT32(pTrident->IOBase, OLDGER_DESTLINEAR, (c)) +#define TGUI_SRCCLIP_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_SRCCLIP_XY, XY_MERGE(x,y)) +#define TGUI_DSTCLIP_XY(x,y) \ + MMIO_OUT32(pTrident->IOBase, GER_DSTCLIP_XY, XY_MERGE(x,y)) +#define TGUI_PATLOC(addr) \ + MMIO_OUT16(pTrident->IOBase, GER_PATLOC, (addr)) +#define TGUI_CKEY(c) \ + MMIO_OUT32(pTrident->IOBase, GER_CKEY, (c)) +#define IMAGEBUSY(b) \ + (b = MMIO_IN32(pTrident->IOBase,IMAGE_GE_STATUS) & 0xF0000000) +#define BLADEBUSY(b) \ + (b = MMIO_IN32(pTrident->IOBase,BLADE_GE_STATUS) & 0xFA800000) +#define IMAGE_OUT(addr, c) \ + MMIO_OUT32(pTrident->IOBase, addr, (c)) +#define BLADE_OUT(addr, c) \ + MMIO_OUT32(pTrident->IOBase, addr, (c)) +#define TGUI_OUTL(addr, c) \ + MMIO_OUT32(pTrident->IOBase, addr, (c)) +#define TGUI_COMMAND(c) \ + MMIO_OUT8(pTrident->IOBase, GER_COMMAND, (c)) +#define OLDTGUI_COMMAND(c) \ + do { \ + OLDTGUI_OPERMODE(GE_OP); \ + OLDTGUISync(); \ + MMIO_OUT32(pTrident->IOBase, OLDGER_COMMAND, (c)); \ + } while (0) + +/* Cyber FP support */ +#define SHADOW_ENABLE(oldval) \ + do {\ + OUTB(0x3CE, CyberControl); \ + oldval = INB(0x3CF);\ + OUTB(0x3CF,oldval | (1 << 6));\ + } while (0) +#define SHADOW_RESTORE(val) \ + do {\ + OUTB(0x3CE, CyberControl); \ + OUTB(0x3CF,val); \ + } while (0); diff --git a/src/trident_shadow.c b/src/trident_shadow.c new file mode 100644 index 0000000..75b24d3 --- /dev/null +++ b/src/trident_shadow.c @@ -0,0 +1,260 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_shadow.c,v 1.3 2001/06/14 02:23:50 keithp Exp $ */ + +/* + Copyright (c) 1999, 2000 The XFree86 Project Inc. + based on code written by Mark Vojkovich <markv@valinux.com> +*/ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "shadowfb.h" +#include "servermd.h" +#include "trident.h" + +void +TRIDENTRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int width, height, Bpp, FBPitch; + unsigned char *src, *dst; + + Bpp = pScrn->bitsPerPixel >> 3; + FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); + + while(num--) { + width = (pbox->x2 - pbox->x1) * Bpp; + height = pbox->y2 - pbox->y1; + src = pTrident->ShadowPtr + (pbox->y1 * pTrident->ShadowPitch) + + (pbox->x1 * Bpp); + dst = pTrident->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); + + while(height--) { + memcpy(dst, src, width); + dst += FBPitch; + src += pTrident->ShadowPitch; + } + + pbox++; + } +} + +void +TRIDENTShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + ScrnInfoPtr pScrn; + pScrn = xf86Screens[pScreen->myNum]; + + (TRIDENTPTR(pScrn))->RefreshArea (pScrn, REGION_NUM_RECTS(damage), + REGION_RECTS(damage)); +} + +void +TRIDENTPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int newX, newY; + + if(pTrident->Rotate == 1) { + newX = pScrn->pScreen->height - y - 1; + newY = x; + } else { + newX = y; + newY = pScrn->pScreen->width - x - 1; + } + + (*pTrident->PointerMoved)(index, newX, newY); +} + +void +TRIDENTRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pTrident->Rotate * pTrident->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* in dwords */ + + if(pTrident->Rotate == 1) { + dstPtr = pTrident->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = pTrident->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = pTrident->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = pTrident->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 8) | + (src[srcPitch * 2] << 16) | + (src[srcPitch * 3] << 24); + src += srcPitch * 4; + } + srcPtr += pTrident->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +TRIDENTRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD16 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pTrident->Rotate * pTrident->ShadowPitch >> 1; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~1; + y2 = (pbox->y2 + 1) & ~1; + height = (y2 - y1) >> 1; /* in dwords */ + + if(pTrident->Rotate == 1) { + dstPtr = (CARD16*)pTrident->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = (CARD16*)pTrident->ShadowPtr + + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD16*)pTrident->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = (CARD16*)pTrident->ShadowPtr + + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 16); + src += srcPitch * 2; + } + srcPtr += pTrident->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +/* this one could be faster */ +void +TRIDENTRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = BitmapBytePad(pScrn->displayWidth * 24); + srcPitch = -pTrident->Rotate * pTrident->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* blocks of 3 dwords */ + + if(pTrident->Rotate == 1) { + dstPtr = pTrident->FbBase + + (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3); + srcPtr = pTrident->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3); + } else { + dstPtr = pTrident->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3); + srcPtr = pTrident->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) | + (src[srcPitch] << 24); + dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) | + (src[srcPitch * 2] << 16) | + (src[(srcPitch * 2) + 1] << 24); + dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) | + (src[(srcPitch * 3) + 1] << 16) | + (src[(srcPitch * 3) + 2] << 24); + dst += 3; + src += srcPitch * 4; + } + srcPtr += pTrident->Rotate * 3; + dstPtr += dstPitch; + } + + pbox++; + } +} + +void +TRIDENTRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count, width, height, dstPitch, srcPitch; + CARD32 *dstPtr, *srcPtr, *src, *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pTrident->Rotate * pTrident->ShadowPitch >> 2; + + while(num--) { + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + if(pTrident->Rotate == 1) { + dstPtr = (CARD32*)pTrident->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; + srcPtr = (CARD32*)pTrident->ShadowPtr + + ((1 - pbox->y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD32*)pTrident->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; + srcPtr = (CARD32*)pTrident->ShadowPtr + + (pbox->y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = dstPtr; + count = height; + while(count--) { + *(dst++) = *src; + src += srcPitch; + } + srcPtr += pTrident->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + diff --git a/src/trident_video.c b/src/trident_video.c new file mode 100644 index 0000000..9c29629 --- /dev/null +++ b/src/trident_video.c @@ -0,0 +1,1408 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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_video.c,v 1.31 2002/12/22 18:54:43 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "trident.h" +#include "trident_regs.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#define OFF_DELAY 800 /* milliseconds */ +#define FREE_DELAY 60000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +static XF86VideoAdaptorPtr TRIDENTSetupImageVideo(ScreenPtr); +static void TRIDENTInitOffscreenImages(ScreenPtr); +static void TRIDENTStopVideo(ScrnInfoPtr, pointer, Bool); +static int TRIDENTSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int TRIDENTGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void TRIDENTQueryBestSize(ScrnInfoPtr, Bool, + short, short, short, short, unsigned int *, unsigned int *, pointer); +static int TRIDENTPutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static int TRIDENTQueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +static void TRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time); +static void tridentSetVideoContrast(TRIDENTPtr pTrident,int value); +static void tridentSetVideoParameters(TRIDENTPtr pTrident, int brightness, + int saturation, int hue); +void tridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame); +static void WaitForSync(ScrnInfoPtr pScrn); + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvColorKey, xvSaturation, xvBrightness, xvHUE, xvContrast; + +void TRIDENTInitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int num_adaptors; + + /* + * The following has been tested on: + * + * 9525 : flags: None + * Cyber9397(DVD) : flags: VID_ZOOM_NOMINI + * CyberBlade/i7: flags: VID_ZOOM_INV | VID_ZOOM_MINI + * CyberBlade/i1: flags: VID_ZOOM_INV | VID_ZOOM_MINI + * CyberBlade/Ai1: flags: VID_ZOOM_INV + * Cyber 9540 : flags: VID_ZOOM_INV | VID_SHIFT_4 + * CyberXPm8 : flags: VID_ZOOM_INV | VID_SHIFT_4 + * + * When you make changes make sure not to break these + * Add new chipsets to this list. + */ + if (pTrident->Chipset >= BLADE3D) { + pTrident->videoFlags = VID_ZOOM_INV ; + if (pTrident->Chipset <= CYBERBLADEI1D) + pTrident->videoFlags |= VID_ZOOM_MINI; + else if (pTrident->Chipset < CYBERBLADEAI1 /* verified EE */ + || pTrident->Chipset > CYBERBLADEAI1D) + pTrident->videoFlags |= VID_OFF_SHIFT_4; + } + if (pTrident->Chipset == CYBER9397 || pTrident->Chipset == CYBER9397DVD) + pTrident->videoFlags = VID_ZOOM_NOMINI; + + if (pTrident->Chipset == CYBER9397DVD || pTrident->Chipset >= CYBER9525DVD) + pTrident->videoFlags |= VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC; + + newAdaptor = TRIDENTSetupImageVideo(pScreen); + TRIDENTInitOffscreenImages(pScreen); + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = /* need to free this someplace */ + xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); + + if (pTrident->videoFlags) + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,3, + "Trident Video Flags: %s %s %s\n", + pTrident->videoFlags & VID_ZOOM_INV ? "VID_ZOOM_INV" : "", + pTrident->videoFlags & VID_ZOOM_MINI ? "VID_ZOOM_MINI" : "", pTrident->videoFlags & VID_OFF_SHIFT_4 ? "VID_OFF_SHIFT_4" + : "", + pTrident->videoFlags & VID_ZOOM_NOMINI ? "VID_ZOOM_NOMINI" + : ""); + +} + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + 1024, 1024, + {1, 1} + } +}; + +#define NUM_FORMATS 4 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#ifdef TRIDENT_XV_GAMMA +#define NUM_ATTRIBUTES 6 +#else +#define NUM_ATTRIBUTES 5 +#endif + +static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 187, "XV_SATURATION"}, + {XvSettable | XvGettable, 0, 0x3F, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 360 , "XV_HUE"}, + {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"} +}; + +#if 0 +# define NUM_IMAGES 4 +#else +# define NUM_IMAGES 4 +#endif + +static XF86ImageRec Images[NUM_IMAGES] = +{ +#if 0 + { + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 15, 0x001F, 0x03E0, 0x7C00, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, +#endif + { + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + XVIMAGE_YV12, + XVIMAGE_YUY2 +}; + +typedef struct { + FBLinearPtr linear; + RegionRec clip; + CARD32 colorKey; + CARD8 Saturation; + CARD8 Brightness; + CARD16 HUE; + INT8 Contrast; + CARD32 videoStatus; + Time offTime; + Time freeTime; + int fixFrame; +} TRIDENTPortPrivRec, *TRIDENTPortPrivPtr; + + +#define GET_PORT_PRIVATE(pScrn) \ + (TRIDENTPortPrivPtr)((TRIDENTPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +void TRIDENTResetVideo(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr; + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + int red, green, blue; + int tmp; + + if (pTrident->Chipset >= CYBER9388) { + OUTW(vgaIOBase + 4, 0x80B9); + OUTW(vgaIOBase + 4, 0x00BE); + OUTW(0x3C4, 0xC057); + OUTW(0x3C4, 0x3420); + OUTW(0x3C4, 0x3037); + } else { + if (pTrident->Chipset >= PROVIDIA9682) { + OUTB(0x83C8, 0x57); + OUTB(0x83C6, 0xC0); + OUTW(vgaIOBase + 4, 0x26BE); + } else { + OUTB(0x83C8, 0x37); + OUTB(0x83C6, 0x01); + OUTB(0x83C8, 0x00); + OUTB(0x83C6, 0x00); + } + } + + if (pTrident->Chipset >= BLADEXP) { + OUTW(0x3C4, 0x007A); + OUTW(0x3C4, 0x007D); + } + switch (pScrn->depth) { + case 8: + VIDEOOUT(pPriv->colorKey, pTrident->keyOffset); + VIDEOOUT(0x00, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); + VIDEOOUT(0x00, (pTrident->keyOffset + 5)); + VIDEOOUT(0x00, (pTrident->keyOffset + 6)); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + tmp = (red << 10) | (green << 5) | (blue); + VIDEOOUT((tmp & 0xff), pTrident->keyOffset); + VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); + VIDEOOUT(0x00, (pTrident->keyOffset + 6)); + break; + case 16: + tmp = (red << 11) | (green << 5) | (blue); + VIDEOOUT((tmp & 0xff), pTrident->keyOffset); + VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); + VIDEOOUT(0x00, (pTrident->keyOffset + 6)); + break; + case 24: + VIDEOOUT(blue, pTrident->keyOffset); + VIDEOOUT(green, (pTrident->keyOffset + 1)); + VIDEOOUT(red, (pTrident->keyOffset + 2)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); + VIDEOOUT(0xFF, (pTrident->keyOffset + 6)); + break; + } + } + + if (pTrident->Chipset >= CYBER9388) { + tridentSetVideoContrast(pTrident,pPriv->Contrast); + tridentSetVideoParameters(pTrident,pPriv->Brightness,pPriv->Saturation, + pPriv->HUE); + } + + OUTW(vgaIOBase + 4, 0x848E); +} + + +static XF86VideoAdaptorPtr +TRIDENTSetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XF86VideoAdaptorPtr adapt; + TRIDENTPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(TRIDENTPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "Trident Backend Scaler"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + pPriv = (TRIDENTPortPrivPtr)(&adapt->pPortPrivates[1]); + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + if (pTrident->Chipset >= CYBER9388) { + adapt->nAttributes = NUM_ATTRIBUTES; + } else { + adapt->nAttributes = 1; /* Just colorkey */ + } + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = TRIDENTStopVideo; + adapt->SetPortAttribute = TRIDENTSetPortAttribute; + adapt->GetPortAttribute = TRIDENTGetPortAttribute; + adapt->QueryBestSize = TRIDENTQueryBestSize; + adapt->PutImage = TRIDENTPutImage; + adapt->QueryImageAttributes = TRIDENTQueryImageAttributes; + + pPriv->colorKey = pTrident->videoKey & ((1 << pScrn->depth) - 1); + pPriv->Brightness = 45; + pPriv->Saturation = 80; + pPriv->Contrast = 4; + pPriv->HUE = 0; + pPriv->videoStatus = 0; + pPriv->fixFrame = 100; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + pTrident->adaptor = adapt; + + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + if (pTrident->Chipset >= CYBER9388) { + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvHUE = MAKE_ATOM("XV_HUE"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + } + + if (pTrident->Chipset >= PROVIDIA9682) + pTrident->keyOffset = 0x50; + else + pTrident->keyOffset = 0x30; + + TRIDENTResetVideo(pScrn); + + return adapt; +} + + +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + +#define DummyScreen screenInfo.screens[0] + +static void +TRIDENTStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + if(shutdown) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + OUTW(vgaIOBase + 4, 0x0091); + WaitForSync(pScrn); + OUTW(vgaIOBase + 4, 0x848E); + } + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback; + } + } +} + +#undef PI +#define PI 3.14159265 + +static void +tridentSetVideoContrast(TRIDENTPtr pTrident,int value) +{ + OUTW(0x3C4, (((value & 0x7)|((value & 0x7) << 4)) << 8) | 0xBC); +} + +static void +tridentSetVideoParameters(TRIDENTPtr pTrident, int brightness, + int saturation, int hue) +{ + double dtmp; + CARD8 sign, tmp, tmp1; + + if (brightness >= 0x20) + brightness -= 0x20; + else + brightness += 0x20; + dtmp = sin((double)hue / 180.0 * PI) * saturation / 12.5; + sign = (dtmp < 0) ? 1 << 1 : 0; + tmp1 = ((int)fabs(dtmp) >> 4) & 0x1; + tmp = brightness << 2 | sign | tmp1; + OUTW(0x3C4, tmp << 8 | 0xB1); + + tmp1 = ((int)fabs(dtmp) & 0x7 ) << 5; + dtmp = cos((double)hue / 180.0 * PI) * saturation / 12.5; + sign = (dtmp < 0) ? 1 << 4 : 0; + tmp1 |= (int)fabs(dtmp) & 0xf; + tmp = sign | tmp1; + OUTW(0x3C4, tmp << 8 | 0xB0); +} + +static int +TRIDENTSetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +){ + TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if(attribute == xvColorKey) { + int red, green, blue; + int tmp; + pPriv->colorKey = value; + switch (pScrn->depth) { + case 8: + VIDEOOUT(pPriv->colorKey, pTrident->keyOffset); + VIDEOOUT(0x00, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + tmp = (red << 10) | (green << 5) | (blue); + VIDEOOUT((tmp&0xff), pTrident->keyOffset); + VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + break; + case 16: + tmp = (red << 11) | (green << 5) | (blue); + VIDEOOUT((tmp&0xff), pTrident->keyOffset); + VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1)); + VIDEOOUT(0x00, (pTrident->keyOffset + 2)); + break; + case 24: + VIDEOOUT(blue, pTrident->keyOffset); + VIDEOOUT(green, (pTrident->keyOffset + 1)); + VIDEOOUT(red, (pTrident->keyOffset + 2)); + break; + } + } + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if (attribute == xvBrightness) { + if ((value < 0) || (value > 0x3f)) + return BadValue; + pPriv->Brightness = value; + tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, + pPriv->HUE); + } else if (attribute == xvSaturation) { + if ((value < 0) || (value > 187)) + return BadValue; + pPriv->Saturation = value; + tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, + pPriv->HUE); + } else if (attribute == xvHUE) { + if ((value < 0) || (value > 360)) + return BadValue; + pPriv->HUE = value; + tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, + pPriv->HUE); + } else if (attribute == xvContrast) { + if ((value < 0) || (value > 7)) + return BadValue; + pPriv->Contrast = value; + tridentSetVideoContrast(pTrident,value); + } else + return BadMatch; + + return Success; +} + +static int +TRIDENTGetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; + + if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else if(attribute == xvBrightness) { + *value = pPriv->Brightness; + } else if(attribute == xvSaturation) { + *value = pPriv->Saturation; + } else if (attribute == xvHUE) { + *value = pPriv->HUE; + } else if (attribute == xvContrast) { + *value = pPriv->Contrast; + } else + return BadMatch; + + return Success; +} + +static void +TRIDENTQueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + *p_w = drw_w; + *p_h = drw_h; + + if(*p_w > 16384) *p_w = 16384; +} + + +static void +TRIDENTCopyData( + unsigned char *src, + unsigned char *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + w <<= 1; + while(h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} + +static void +TRIDENTCopyMungedData( + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w +){ + CARD32 *dst = (CARD32*)dst1; + int i, j; + + dstPitch >>= 2; + w >>= 1; + + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) { + dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | + (src3[i] << 8) | (src2[i] << 24); + } + dst += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} + +static FBLinearPtr +TRIDENTAllocateMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + } + + return new_linear; +} + +static void +TRIDENTDisplayVideo( + ScrnInfoPtr pScrn, + int id, + int offset, + short width, short height, + int pitch, + int x1, int y1, int x2, int y2, + BoxPtr dstBox, + short src_w, short src_h, + short drw_w, short drw_h +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + int zoomx1, zoomx2, zoomy1, zoomy2; + int tx1,tx2; + int ty1,ty2; + + switch(id) { + case 0x35315652: /* RGB15 */ + case 0x36315652: /* RGB16 */ + if (pTrident->Chipset >= CYBER9388) { + OUTW(vgaIOBase + 4, 0x22BF); + OUTW(vgaIOBase + 4, 0x248F); + } else { + OUTW(vgaIOBase + 4, 0x118F); + } + break; + case FOURCC_YV12: /* YV12 */ + case FOURCC_YUY2: /* YUY2 */ + default: + if (pTrident->Chipset >= CYBER9388) { + OUTW(vgaIOBase + 4, 0x00BF); + OUTW(vgaIOBase + 4, 0x208F); + } else { + OUTW(vgaIOBase + 4, 0x108F); + } + break; + } + tx1 = dstBox->x1 + pTrident->hsync; + tx2 = dstBox->x2 + pTrident->hsync + pTrident->hsync_rskew; + ty1 = dstBox->y1 + pTrident->vsync - 2; + ty2 = dstBox->y2 + pTrident->vsync + 2 + pTrident->vsync_bskew; + + OUTW(vgaIOBase + 4, (tx1 & 0xff) <<8 | 0x86); + OUTW(vgaIOBase + 4, (tx1 & 0xff00) | 0x87); + OUTW(vgaIOBase + 4, (ty1 & 0xff) <<8 | 0x88); + OUTW(vgaIOBase + 4, (ty1 & 0xff00) | 0x89); + OUTW(vgaIOBase + 4, (tx2 & 0xff) <<8 | 0x8A); + OUTW(vgaIOBase + 4, (tx2 & 0xff00) | 0x8B); + OUTW(vgaIOBase + 4, (ty2 & 0xff) <<8 | 0x8C); + OUTW(vgaIOBase + 4, (ty2 & 0xff00) | 0x8D); + + offset += (x1 >> 15) & ~0x01; + + if (pTrident->videoFlags & VID_OFF_SHIFT_4) + offset = offset >> 4; + else + offset = offset >> 3; + + OUTW(vgaIOBase + 4, (((width<<1) & 0xff)<<8) | 0x90); + OUTW(vgaIOBase + 4, ((width<<1) & 0xff00) | 0x91); + OUTW(vgaIOBase + 4, ((offset) & 0xff) << 8 | 0x92); + OUTW(vgaIOBase + 4, ((offset) & 0xff00) | 0x93); + OUTW(vgaIOBase + 4, ((offset) & 0x070000) >> 8 | 0x94); + + /* Horizontal Zoom */ + if (pTrident->videoFlags & VID_ZOOM_INV) { + if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_w > drw_w) + zoomx2 = (int)((float)drw_w/(float)src_w * 1024) + | (((int)((float)src_w/(float)drw_w) - 1)&7)<<10 | 0x8000; + else + zoomx2 = (int)(float)src_w/(float)drw_w * 1024; + + OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); + OUTW(vgaIOBase + 4, (zoomx2&0x9f00) | 0x81); + } else { + if (drw_w == src_w + || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_w > drw_w))) { + OUTW(vgaIOBase + 4, 0x0080); + OUTW(vgaIOBase + 4, 0x0081); + } else + if (drw_w > src_w) { + float z; + + z = (float)((drw_w)/(float)src_w) - 1.0; + + zoomx1 = z; + zoomx2 = (z - (int)zoomx1 ) * 1024; + + OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); + OUTW(vgaIOBase + 4, (zoomx1&0x0f)<<10 | (zoomx2&0x0300) |0x81); + } else { + zoomx1 = ((float)drw_w/(float)src_w); + zoomx2 = ( ((float)drw_w/(float)src_w) - (int)zoomx1 ) * 1024; + OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); + OUTW(vgaIOBase + 4, (zoomx2&0x0300)| + (((int)((float)src_w/(float)drw_w)-1)&7)<<10 | 0x8081); + } + } + + /* Vertical Zoom */ + if (pTrident->videoFlags & VID_ZOOM_INV) { + if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_h > drw_h) + zoomy2 = (int)(( ((float)drw_h/(float)src_h)) * 1024) + | (((int)((float)src_h/(float)drw_h)-1)&7)<<10 + | 0x8000; + else + zoomy2 = ( ((float)src_h/(float)drw_h)) * 1024; + OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); + OUTW(vgaIOBase + 4, (zoomy2&0x9f00) | 0x0083); + } else { + if (drw_h == src_h + || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_h > drw_h))) { + OUTW(vgaIOBase + 4, 0x0082); + OUTW(vgaIOBase + 4, 0x0083); + } else + if (drw_h > src_h) { + float z; + + z = (float)drw_h/(float)src_h - 1; + zoomy1 = z; + zoomy2 = (z - (int)zoomy1 ) * 1024; + + OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); + OUTW(vgaIOBase + 4, (zoomy1&0x0f)<<10 | (zoomy2&0x0300) |0x83); + } else { + zoomy1 = ((float)drw_h/(float)src_h); + zoomy2 = ( ((float)drw_h/(float)src_h) - (int)zoomy1 ) * 1024; + OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); + OUTW(vgaIOBase + 4, (zoomy2&0x0300)| + (((int)((float)src_h/(float)drw_h)-1)&7)<<10 | 0x8083); + } + } + + if (pTrident->Chipset >= CYBER9388) { + int lb = (width+2) >> 2; + + OUTW(vgaIOBase + 4, ((lb & 0x100)>>1) | 0x0895); + OUTW(vgaIOBase + 4, (lb & 0xFF)<<8 | 0x0096); + if ((pTrident->videoFlags & VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC) + && (src_w > 384)) { + OUTW(0x3C4, 0x0497); /* 2x line buffers */ + } else { + OUTW(0x3C4, 0x0097); /* 1x line buffers */ + } + OUTW(vgaIOBase + 4, 0x8097); + OUTW(vgaIOBase + 4, 0x00BA); + OUTW(vgaIOBase + 4, 0x00BB); + OUTW(vgaIOBase + 4, 0xFFBC); + OUTW(vgaIOBase + 4, 0xFFBD); + OUTW(vgaIOBase + 4, 0x04BE); + OUTW(vgaIOBase + 4, 0x948E); + } else { + + OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2)) + ? (width >> 2) : (width >> 6)) << 8) | 0x95); + OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2)) + ? ((width+2) >> 2) : ((width+2) >> 6)) << 8) |0x96); + + OUTW(vgaIOBase + 4, 0x948E); + OUTB(0x83C8, 0x00); + OUTB(0x83C6, 0x95); + } +} + +static int +TRIDENTPutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data +){ + TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int pitch, new_size, offset, offset2 = 0, offset3 = 0; + int srcPitch, srcPitch2 = 0, dstPitch; + int top, left, npixels, nlines, bpp; + BoxRec dstBox; + CARD32 tmp; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + width, height)) + return Success; + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + bpp = pScrn->bitsPerPixel >> 3; + pitch = bpp * pScrn->displayWidth; + + dstPitch = ((width << 1) + 15) & ~15; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + srcPitch = (width + 3) & ~3; + offset2 = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + offset3 = (srcPitch2 * (height >> 1)) + offset2; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = (width << 1); + break; + } + + if(!(pPriv->linear = TRIDENTAllocateMemory(pScrn, pPriv->linear, new_size))) + return BadAlloc; + + /* copy data */ + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + left <<= 1; + + offset = pPriv->linear->offset * bpp; + + dst_start = pTrident->FbBase + offset + left + (top * dstPitch); + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + if(id == FOURCC_I420) { + tmp = offset2; + offset2 = offset3; + offset3 = tmp; + } + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + TRIDENTCopyMungedData(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + buf += (top * srcPitch) + left; + nlines = ((y2 + 0xffff) >> 16) - top; + TRIDENTCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + break; + } + + /* update cliplist */ + if(!RegionsEqual(&pPriv->clip, clipBoxes)) { + /* update cliplist */ + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); + } + + offset += top * dstPitch; + + tridentFixFrame(pScrn,&pPriv->fixFrame); + TRIDENTDisplayVideo(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + return Success; +} + +static int +TRIDENTQueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int size, tmp; + + if(*w > 1024) *w = 1024; + if(*h > 1024) *h = 1024; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: /* YV12 */ + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + default: /* RGB15, RGB16, YUY2 */ + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; +} + +/****************** Offscreen stuff ***************/ + +typedef struct { + FBLinearPtr linear; + Bool isOn; +} OffscreenPrivRec, * OffscreenPrivPtr; + +static int +TRIDENTAllocateSurface( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +){ + FBLinearPtr linear; + int pitch, fbpitch, size, bpp; + OffscreenPrivPtr pPriv; + + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + fbpitch = bpp * pScrn->displayWidth; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = TRIDENTAllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = xalloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = xalloc(sizeof(int)))) { + xfree(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { + xfree(surface->pitches); + xfree(surface->offsets); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + + pPriv->linear = linear; + pPriv->isOn = FALSE; + + surface->pScrn = pScrn; + surface->id = id; + surface->pitches[0] = pitch; + surface->offsets[0] = linear->offset * bpp; + surface->devPrivate.ptr = (pointer)pPriv; + + return Success; +} + +static int +TRIDENTStopSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) { + TRIDENTPtr pTrident = TRIDENTPTR(surface->pScrn); + int vgaIOBase = VGAHWPTR(surface->pScrn)->IOBase; + + OUTW(vgaIOBase + 4, 0x0091); + WaitForSync(surface->pScrn); + OUTW(vgaIOBase + 4, 0x848E); + pPriv->isOn = FALSE; + } + + return Success; +} + + +static int +TRIDENTFreeSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) + TRIDENTStopSurface(surface); + xf86FreeOffscreenLinear(pPriv->linear); + xfree(surface->pitches); + xfree(surface->offsets); + xfree(surface->devPrivate.ptr); + + return Success; +} + +static int +TRIDENTGetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +){ + return TRIDENTGetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + +static int +TRIDENTSetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +){ + return TRIDENTSetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + +static int +TRIDENTDisplaySurface( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + ScrnInfoPtr pScrn = surface->pScrn; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTPortPrivPtr portPriv = pTrident->adaptor->pPortPrivates[0].ptr; + INT32 x1, y1, x2, y2; + BoxRec dstBox; + + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + surface->width, surface->height)) + { + return Success; + } + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + TRIDENTResetVideo(pScrn); + + tridentFixFrame(pScrn,&portPriv->fixFrame); + TRIDENTDisplayVideo(pScrn, surface->id, surface->offsets[0], + surface->width, surface->height, surface->pitches[0], + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + + xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); + + pPriv->isOn = TRUE; + /* we've prempted the XvImage stream so set its free timer */ + if(portPriv->videoStatus & CLIENT_VIDEO_ON) { + REGION_EMPTY(pScrn->pScreen, &portPriv->clip); + UpdateCurrentTime(); + portPriv->videoStatus = FREE_TIMER; + portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback; + } + + return Success; +} + +static void +TRIDENTInitOffscreenImages(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XF86OffscreenImagePtr offscreenImages; + + /* need to free this someplace */ + if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) + return; + + offscreenImages[0].image = &Images[0]; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].alloc_surface = TRIDENTAllocateSurface; + offscreenImages[0].free_surface = TRIDENTFreeSurface; + offscreenImages[0].display = TRIDENTDisplaySurface; + offscreenImages[0].stop = TRIDENTStopSurface; + offscreenImages[0].setAttribute = TRIDENTSetSurfaceAttribute; + offscreenImages[0].getAttribute = TRIDENTGetSurfaceAttribute; + offscreenImages[0].max_width = 1024; + offscreenImages[0].max_height = 1024; + if (pTrident->Chipset >= CYBER9388) { + offscreenImages[0].num_attributes = NUM_ATTRIBUTES; + } else { + offscreenImages[0].num_attributes = 1; /* just colorkey */ + } + offscreenImages[0].attributes = Attributes; + + xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); +} + +static void +TRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr; + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + if(pPriv->videoStatus & TIMER_MASK) { + if(pPriv->videoStatus & OFF_TIMER) { + if(pPriv->offTime < time) { + OUTW(vgaIOBase + 4, 0x0091); + WaitForSync(pScrn); + OUTW(vgaIOBase + 4, 0x848E); + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = time + FREE_DELAY; + } + } else { /* FREE_TIMER */ + if(pPriv->freeTime < time) { + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + pTrident->VideoTimerCallback = NULL; + } + } + } else /* shouldn't get here */ + pTrident->VideoTimerCallback = NULL; +} + + /* Calculate skew offsets for video overlay */ + + +void +tridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame) +{ + + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + int HTotal, HSyncStart; + int VTotal, VSyncStart; + int h_off = 0; + int v_off = 0; + unsigned char CRTC[0x11]; + Bool isShadow; + unsigned char shadow = 0; + + if ((*fixFrame)++ < 100) + return; + + *fixFrame = 0; + + OUTB(0x3CE, CyberControl); + isShadow = ((INB(0x3CF) & 0x81) == 0x81); + + if (isShadow) + SHADOW_ENABLE(shadow); + + OUTB(vgaIOBase + 4, 0x0); + CRTC[0x0] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4, 0x4); + CRTC[0x4] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4, 0x5); + CRTC[0x5] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4, 0x6); + CRTC[0x6] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4, 0x7); + CRTC[0x7] = INB(vgaIOBase + 5); + OUTB(vgaIOBase + 4, 0x10); + CRTC[0x10] = INB(vgaIOBase + 5); + + HTotal = CRTC[0] << 3; + VTotal = CRTC[6] + | ((CRTC[7] & (1<<0)) << 8) + | ((CRTC[7] & (1<<5)) << 4); + HSyncStart = (CRTC[4] + + ((CRTC[5] >> 5) & 0x3)) << 3; + VSyncStart = CRTC[0x10] + | ((CRTC[7] & (1<<2)) << 6) + | ((CRTC[7] & (1<<7)) << 2); + + if (isShadow) { + SHADOW_RESTORE(shadow); + if (pTrident->lcdMode != 0xff) { + h_off = (LCD[pTrident->lcdMode].display_x + - pScrn->currentMode->HDisplay) >> 1; + v_off = (LCD[pTrident->lcdMode].display_y + - pScrn->currentMode->VDisplay) >> 1; + } + } + + pTrident->hsync = (HTotal - HSyncStart) + 23 + h_off; + pTrident->vsync = (VTotal - VSyncStart) - 2 + v_off; + pTrident->hsync_rskew = 0; + pTrident->vsync_bskew = 0; + + /* + * HACK !! As awful as this is, it appears to be the only way....Sigh! + * We have XvHsync and XvVsync as options now, which adjust + * at the very end of this function. It'll be helpful for now + * and we can get more data on some of these skew values. + */ + switch (pTrident->Chipset) { + case TGUI9680: + /* Furthur tweaking needed */ + pTrident->hsync -= 84; + pTrident->vsync += 2; + break; + case PROVIDIA9682: + /* Furthur tweaking needed */ + pTrident->hsync += 7; + break; + case PROVIDIA9685: + /* Spot on */ + break; + case BLADEXP: + case CYBERBLADEXPAI1: + pTrident->hsync -= 15; + pTrident->hsync_rskew = 3; + break; + case BLADE3D: + if (pScrn->depth == 24) + pTrident->hsync -= 8; + else + pTrident->hsync -= 6; + break; + case CYBERBLADEI7: + case CYBERBLADEI7D: + case CYBERBLADEI1: + case CYBERBLADEI1D: + pTrident->hsync -= 8; + break; + case CYBERBLADEAI1: + pTrident->hsync -= 7; + break; + case CYBERBLADEAI1D: + pTrident->vsync += 2; + pTrident->vsync_bskew = -4; + pTrident->hsync -= 5; + break; + case CYBERBLADEE4: + pTrident->hsync -= 8; + break; + case CYBER9397: + pTrident->hsync -= 1; + pTrident->vsync -= 0; + pTrident->vsync_bskew = 0; + break; + case CYBER9397DVD: + pTrident->hsync_rskew = -1; + pTrident->vsync_bskew = -1; + break; + } + pTrident->hsync+=pTrident->OverrideHsync; + pTrident->vsync+=pTrident->OverrideVsync; + pTrident->hsync_rskew += pTrident->OverrideRskew; + pTrident->vsync_bskew += pTrident->OverrideBskew; +} + +static void +WaitForSync(ScrnInfoPtr pScrn) +{ + register vgaHWPtr hwp = VGAHWPTR(pScrn); + + while (!(hwp->readST01(hwp)&0x8)) {}; + while (hwp->readST01(hwp)&0x8) {}; +} diff --git a/src/tridenthelper.c b/src/tridenthelper.c new file mode 100644 index 0000000..f8e5905 --- /dev/null +++ b/src/tridenthelper.c @@ -0,0 +1,341 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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/tridenthelper.c,v 1.20 2001/10/28 03:33:52 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "vgaHW.h" + +#include "trident.h" +#include "trident_regs.h" + +static void IsClearTV(ScrnInfoPtr pScrn); + +void +TGUISetClock(ScrnInfoPtr pScrn, int clock, CARD8 *a, CARD8 *b) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int powerup[4] = { 1,2,4,8 }; + int clock_diff = 750; + int freq, ffreq; + int m, n, k; + int p, q, r, s; + int endn, endm, endk, startk; + + p = q = r = s = 0; + + IsClearTV(pScrn); + + if (pTrident->NewClockCode) + { + endn = 255; + endm = 63; + endk = 2; + if (clock >= 100000) startk = 0; else + if (clock >= 50000) startk = 1; else + startk = 2; + } + else + { + endn = 121; + endm = 31; + endk = 1; + if (clock > 50000) startk = 1; else + startk = 0; + } + + freq = clock; + + for (k=startk;k<=endk;k++) + for (n=0;n<=endn;n++) + for (m=1;m<=endm;m++) + { + ffreq = ( ( ((n + 8) * pTrident->frequency) / ((m + 2) * powerup[k]) ) * 1000); + if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff)) + { +/* + * It seems that the 9440 docs have this STRICT limitation, although + * most 9440 boards seem to cope. 96xx/Cyber chips don't need this limit + * so, I'm gonna remove it and it allows lower clocks < 25.175 too ! + */ +#ifdef STRICT + if ( (n+8)*100/(m+2) < 978 && (n+8)*100/(m+2) > 349 ) { +#endif + clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq; + p = n; q = m; r = k; s = ffreq; +#ifdef STRICT + } +#endif + } + } + + if (s == 0) + { + FatalError("Unable to set programmable clock.\n" + "Frequency %d is not a valid clock.\n" + "Please modify XF86Config for a new clock.\n", + freq); + } + + if (pTrident->NewClockCode) + { + /* N is all 8bits */ + *a = p; + /* M is first 6bits, with K last 2bits */ + *b = (q & 0x3F) | (r << 6); + } + else + { + /* N is first 7bits, first M bit is 8th bit */ + *a = ((1 & q) << 7) | p; + /* first 4bits are rest of M, 1bit for K value */ + *b = (((q & 0xFE) >> 1) | (r << 4)); + } + xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,3,"Found Clock %6.2f n=%i m=%i" + " k=%i\n",clock/1000.,p,q,r); +} + +static void +IsClearTV(ScrnInfoPtr pScrn) +{ + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp; + + if (pTrident->frequency != 0) return; + + OUTB(vgaIOBase + 4, 0xC0); + temp = INB(vgaIOBase + 5); + if (temp & 0x80) + pTrident->frequency = PAL; + else + pTrident->frequency = NTSC; +} + +void +TridentFindClock(ScrnInfoPtr pScrn, int clock) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->MUX = FALSE; +#ifdef READOUT + pTrident->DontSetClock = FALSE; +#endif + pTrident->currentClock = clock; + + if (pTrident->IsCyber) { + Bool LCDActive; +#ifdef READOUT + Bool ShadowModeActive; + Bool HStretch; + Bool VStretch; +#endif + OUTB(0x3CE, FPConfig); + LCDActive = (INB(0x3CF) & 0x10); +#ifdef READOUT + OUTB(0x3CE,HorStretch); + HStretch = (INB(0x3CF) & 0x01); + OUTB(0x3CE,VertStretch); + VStretch = (INB(0x3CF) & 0x01); + + if (!(VStretch || HStretch) && LCDActive) { + CARD8 temp; + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + pTrident->MUX = ((INB(0x3C6) & 0x20) == 0x20); + temp = INB(0x3C8); + pTrident->DontSetClock = TRUE; + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Keeping Clock for LCD Mode\n"); + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"MUX is %s\n",pTrident->MUX? + "on":"off"); + return; + + } else +#endif + { + if (pTrident->lcdMode != 0xff && LCDActive) + pTrident->currentClock = clock = LCD[pTrident->lcdMode].clock; + } + + } + if (clock > pTrident->MUXThreshold) pTrident->MUX = TRUE; + else pTrident->MUX = FALSE; + +} + +float +CalculateMCLK(ScrnInfoPtr pScrn) +{ + int vgaIOBase = VGAHWPTR(pScrn)->IOBase; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int a,b; + int m,n,k; + float freq = 0.0; + int powerup[4] = { 1,2,4,8 }; + CARD8 temp; + + if (pTrident->HasSGRAM) { + OUTB(vgaIOBase + 4, 0x28); + switch(INB(vgaIOBase + 5) & 0x07) { + case 0: + freq = 60; + break; + case 1: + freq = 78; + break; + case 2: + freq = 90; + break; + case 3: + freq = 120; + break; + case 4: + freq = 66; + break; + case 5: + freq = 83; + break; + case 6: + freq = 100; + break; + case 7: + freq = 132; + break; + } + } else { + OUTB(0x3C4, NewMode1); + temp = INB(0x3C5); + + OUTB(0x3C5, 0xC2); + if (!Is3Dchip) { + a = INB(0x43C6); + b = INB(0x43C7); + } else { + OUTB(0x3C4, 0x16); + a = INB(0x3C5); + OUTB(0x3C4, 0x17); + b = INB(0x3C5); + } + + OUTB(0x3C4, NewMode1); + OUTB(0x3C5, temp); + + IsClearTV(pScrn); + + if (pTrident->NewClockCode) { + m = b & 0x3F; + n = a; + k = (b & 0xC0) >> 6; + } else { + m = (a & 0x07); + k = (b & 0x02) >> 1; + n = ((a & 0xF8)>>3)|((b&0x01)<<5); + } + + freq = ((n+8)*pTrident->frequency)/((m+2)*powerup[k]); + } + return (freq); +} + +void +TGUISetMCLK(ScrnInfoPtr pScrn, int clock, CARD8 *a, CARD8 *b) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int powerup[4] = { 1,2,4,8 }; + int clock_diff = 750; + int freq, ffreq; + int m,n,k; + int p, q, r, s; + int startn, endn; + int endm, endk; + + p = q = r = s = 0; + + IsClearTV(pScrn); + + if (pTrident->NewClockCode) + { + startn = 64; + endn = 255; + endm = 63; + endk = 3; + } + else + { + startn = 0; + endn = 121; + endm = 31; + endk = 1; + } + + freq = clock; + + if (!pTrident->HasSGRAM) { + for (k=0;k<=endk;k++) + for (n=startn;n<=endn;n++) + for (m=1;m<=endm;m++) { + ffreq = ((((n+8)*pTrident->frequency)/((m+2)*powerup[k]))*1000); + if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff)) + { + clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq; + p = n; q = m; r = k; s = ffreq; + } + } + + if (s == 0) + { + FatalError("Unable to set memory clock.\n" + "Frequency %d is not a valid clock.\n" + "Please modify XF86Config for a new clock.\n", + freq); + } + + if (pTrident->NewClockCode) + { + /* N is all 8bits */ + *a = p; + /* M is first 6bits, with K last 2bits */ + *b = (q & 0x3F) | (r << 6); + } + else + { + /* N is first 7bits, first M bit is 8th bit */ + *a = ((1 & q) << 7) | p; + /* first 4bits are rest of M, 1bit for K value */ + *b = (((q & 0xFE) >> 1) | (r << 4)); + } + } +} + + + + diff --git a/src/tridentramdac.c b/src/tridentramdac.c new file mode 100644 index 0000000..f4117b9 --- /dev/null +++ b/src/tridentramdac.c @@ -0,0 +1,67 @@ +/* + * Copyright 1992-2000 by Alan Hourihane, Wigan, England. + * + * 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * TridentOutIndReg() and TridentInIndReg() are used to access + * the indirect Trident RAMDAC registers only. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/tridentramdac.c,v 1.4 2000/12/07 16:48:06 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "trident_regs.h" +#include "trident.h" + +void +TridentWriteAddress(ScrnInfoPtr pScrn, CARD32 index) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + MMIO_OUTB(0x3C6, 0xFF); + MMIO_OUTB(0x3C8, index); +} + +void +TridentWriteData(ScrnInfoPtr pScrn, unsigned char data) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + MMIO_OUTB(0x3C9, data); +} + +void +TridentReadAddress(ScrnInfoPtr pScrn, CARD32 index) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + MMIO_OUTB(0x3C6, 0xFF); + MMIO_OUTB(0x3C7, index); +} + +unsigned char +TridentReadData(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + return(MMIO_INB(0x3C9)); +} diff --git a/src/tvga_dac.c b/src/tvga_dac.c new file mode 100644 index 0000000..2d5a7ec --- /dev/null +++ b/src/tvga_dac.c @@ -0,0 +1,231 @@ +/* + * Copyright 1992-1999 by Alan Hourihane, Wigan, England. + * + * 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/tvga_dac.c,v 1.6 2002/03/29 18:33:29 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "vgaHW.h" + +#include "trident.h" +#include "trident_regs.h" + +Bool +TVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + TRIDENTRegPtr pReg = &pTrident->ModeReg; + int vgaIOBase; + int offset = 0; + int clock = mode->Clock; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + OUTB(0x3C4, 0x0B); INB(0x3C5); /* Ensure we are in New Mode */ + + pReg->tridentRegsDAC[0x00] = 0x00; + OUTB(0x3C4, ConfPort2); + pReg->tridentRegs3C4[ConfPort2] = INB(0x3C5); + OUTB(0x3CE, MiscExtFunc); + pReg->tridentRegs3CE[MiscExtFunc] = INB(0x3CF) & 0xF0; + OUTB(vgaIOBase + 4, FIFOControl); + pReg->tridentRegs3x4[FIFOControl] = INB(vgaIOBase + 5) | 0x24; + + if (pScrn->bitsPerPixel >= 8) { + /* YUK ! here we have to mess with old mode operation */ + OUTB(0x3C4, 0x0B); OUTB(0x3C5, 0x00); /* Goto Old Mode */ + OUTB(0x3C4, OldMode2 + NewMode2); + pReg->tridentRegs3C4[OldMode2] = 0x10; + OUTB(0x3C4, 0x0B); INB(0x3C5); /* Back to New Mode */ + pReg->tridentRegs3x4[Underline] = 0x40; + if (pTrident->Chipset < TGUI9440AGi) + pReg->tridentRegs3x4[CRTCMode] = 0xA3; + } + + if (pScrn->videoRam > 512) + pReg->tridentRegs3C4[ConfPort2] |= 0x20; + else + pReg->tridentRegs3C4[ConfPort2] &= 0xDF; + + switch (pScrn->bitsPerPixel) { + case 1: + case 4: + offset = pScrn->displayWidth >> 4; + break; + case 8: + if (pScrn->videoRam < 1024) + offset = pScrn->displayWidth >> 3; + else + offset = pScrn->displayWidth >> 4; + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + break; + case 16: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = pScrn->displayWidth >> 3; + /* Reload with any chipset specific stuff here */ + if (pTrident->Chipset == TVGA8900D) { + if (pScrn->depth == 15) + pReg->tridentRegsDAC[0x00] = 0xA0; + else + pReg->tridentRegsDAC[0x00] = 0xE0; + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Div by 2*/ + clock *= 2; /* Double the clock */ + } + break; + case 24: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = (pScrn->displayWidth * 3) >> 3; + pReg->tridentRegsDAC[0x00] = 0xD0; + break; + case 32: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; /* Clock Division by 2*/ + clock *= 2; /* Double the clock */ + offset = pScrn->displayWidth >> 1; + pReg->tridentRegsDAC[0x00] = 0x42; + break; + } + pReg->tridentRegs3x4[Offset] = offset & 0xFF; + + pReg->tridentRegsClock[0x00] = mode->ClockIndex; + + pReg->tridentRegs3C4[NewMode1] = 0x80; + + if (pTrident->Linear) + pReg->tridentRegs3x4[LinearAddReg] = ((pTrident->FbAddress >> 24) << 6)| + ((pTrident->FbAddress >> 20) & 0x0F)| + 0x20; + else { + pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; + pReg->tridentRegs3x4[LinearAddReg] = 0; + } + + pReg->tridentRegs3x4[CRTCModuleTest] = + (mode->Flags & V_INTERLACE ? 0x84 : 0x80); + OUTB(vgaIOBase+ 4, AddColReg); + pReg->tridentRegs3x4[AddColReg] = (INB(vgaIOBase + 5) & 0xCF) | + ((offset & 0x100) >> 4); + + return(TRUE); +} + +void +TVGARestore(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp; + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + /* Goto Old Mode */ + OUTB(0x3C4, 0x0B); + OUTB(0x3C5, 0x00); + OUTB(0x3C4, OldMode2 + NewMode2); + OUTB(0x3C5, tridentReg->tridentRegs3C4[OldMode2]); + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + temp = INB(0x3C5); + + /* Unprotect registers */ + OUTW(0x3C4, (0x80 << 8) | NewMode1); + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); + temp = INB(0x3C8); + + OUTW_3x4(CRTCModuleTest); + OUTW_3x4(LinearAddReg); + OUTW_3x4(FIFOControl); + OUTW_3C4(ConfPort2); + if (pScrn->bitsPerPixel >= 8) { + OUTW_3x4(Underline); + if (pTrident->Chipset < TGUI9440AGi) + OUTW_3x4(CRTCMode); + } + OUTW_3x4(AddColReg); + OUTW_3CE(MiscExtFunc); + OUTW_3x4(Offset); + + TRIDENTClockSelect(pScrn, tridentReg->tridentRegsClock[0x00]); + + OUTW(0x3C4, ((tridentReg->tridentRegs3C4[NewMode1]) << 8)| NewMode1); +} + +void +TVGASave(ScrnInfoPtr pScrn, TRIDENTRegPtr tridentReg) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD8 temp; + int vgaIOBase; + vgaIOBase = VGAHWPTR(pScrn)->IOBase; + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); + temp = INB(0x3C8); + + /* Goto Old Mode */ + OUTB(0x3C4, 0x0B); + OUTB(0x3C5, 0x00); + OUTB(0x3C4, OldMode2 + NewMode2); + tridentReg->tridentRegs3C4[OldMode2] = INB(0x3C5); + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + temp = INB(0x3C5); + + INB_3C4(NewMode1); + + /* Unprotect registers */ + OUTW(0x3C4, ((0x80 ^ 0x02) << 8) | NewMode1); + OUTW(vgaIOBase + 4, (0x92 << 8) | NewMode1); + + if (pScrn->bitsPerPixel >= 8) { + INB_3x4(Underline); + if (pTrident->Chipset < TGUI9440AGi) + INB_3x4(CRTCMode); + } + INB_3x4(LinearAddReg); + INB_3x4(FIFOControl); + INB_3x4(CRTCModuleTest); + INB_3x4(AddColReg); + INB_3CE(MiscExtFunc); + INB_3C4(ConfPort2); + + TRIDENTClockSelect(pScrn, CLK_REG_SAVE); + + /* Protect registers */ + OUTW_3C4(NewMode1); +} diff --git a/src/xp_accel.c b/src/xp_accel.c new file mode 100644 index 0000000..f6f0b63 --- /dev/null +++ b/src/xp_accel.c @@ -0,0 +1,601 @@ +/* + * Copyright 1992-2002 by Alan Hourihane, Sychdyn, 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * BladeXP accelerated options. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/xp_accel.c,v 1.4 2002/10/09 16:38:20 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "miline.h" + +#include "trident.h" +#include "trident_regs.h" + +#include "xaalocal.h" +#include "xaarop.h" + +static void XPSync(ScrnInfoPtr pScrn); +#if 0 +static void XPSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int length, + unsigned char *pattern); +static void XPSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant, int phase); +static void XPSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void XPSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, + int len, int octant); +#endif +static void XPSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, + int len, int dir); +static void XPSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void XPSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, + int y, int w, int h); +static void XPSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, + int y2, int w, int h); +static void XPSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int transparency_color); +static void XPSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, int fg, int bg, + int rop, unsigned int planemask); +static void XPSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#if 0 +static void XPSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void XPSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft); +static void XPSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); +#endif + +static void +XPInitializeAccelerator(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int shift; + + /* This forces updating the clipper */ + pTrident->Clipping = TRUE; + + CHECKCLIPPING; + + BLADE_XP_OPERMODE(pTrident->EngineOperation); + pTrident->EngineOperation |= 0x40; + switch (pScrn->bitsPerPixel) { + case 8: + default: /* Muffle compiler */ + shift = 18; + break; + case 16: + shift = 19; + break; + case 32: + shift = 20; + break; + } + MMIO_OUT32(pTrident->IOBase, 0x2154, (pScrn->displayWidth) << shift); + MMIO_OUT32(pTrident->IOBase, 0x2150, (pScrn->displayWidth) << shift); + MMIO_OUT8(pTrident->IOBase, 0x2126, 3); +} + +Bool +XPAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + BoxRec AvailFBArea; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (pTrident->FbMapSize - 4096) / (pScrn->displayWidth * + pScrn->bitsPerPixel / 8); + + if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047; + + xf86InitFBManager(pScreen, &AvailFBArea); + + if (pTrident->NoAccel) + return FALSE; + + pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + infoPtr->Flags = PIXMAP_CACHE | + OFFSCREEN_PIXMAPS | + LINEAR_FRAMEBUFFER; + + pTrident->InitializeAccelerator = XPInitializeAccelerator; + XPInitializeAccelerator(pScrn); + + infoPtr->Sync = XPSync; + +#if 0 /* TO DO for the XP */ + infoPtr->SolidLineFlags = NO_PLANEMASK; + infoPtr->SetupForSolidLine = XPSetupForSolidLine; + infoPtr->SolidBresenhamLineErrorTermBits = 12; + infoPtr->SubsequentSolidBresenhamLine = XPSubsequentSolidBresenhamLine; + + infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | + NO_PLANEMASK | + LINE_PATTERN_POWER_OF_2_ONLY; + infoPtr->SetupForDashedLine = XPSetupForDashedLine; + infoPtr->DashedBresenhamLineErrorTermBits = 12; + infoPtr->SubsequentDashedBresenhamLine = + XPSubsequentDashedBresenhamLine; + infoPtr->DashPatternMaxLength = 16; +#endif + + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = XPSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = XPSubsequentFillRectSolid; + infoPtr->SubsequentSolidHorVertLine = XPSubsequentSolidHorVertLine; + + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY; + + infoPtr->SetupForScreenToScreenCopy = + XPSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + XPSubsequentScreenToScreenCopy; + + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_PROGRAMMED_BITS | + BIT_ORDER_IN_BYTE_MSBFIRST; + + infoPtr->SetupForMono8x8PatternFill = + XPSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + XPSubsequentMono8x8PatternFillRect; + +#if 0 /* Needs fixing */ + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST; + + pTrident->XAAScanlineColorExpandBuffers[0] = + xnfalloc(((pScrn->virtualX + 63)) *4* (pScrn->bitsPerPixel / 8)); + + infoPtr->NumScanlineColorExpandBuffers = 1; + infoPtr->ScanlineColorExpandBuffers = + pTrident->XAAScanlineColorExpandBuffers; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + XPSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + XPSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = + XPSubsequentColorExpandScanline; +#endif + + return(XAAInit(pScreen, infoPtr)); +} + +static void +XPSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count = 0, timeout = 0; + int busy; + + BLADE_XP_OPERMODE(pTrident->EngineOperation); + + for (;;) { + BLTBUSY(busy); + if (busy != GE_BUSY) { + return; + } + count++; + if (count == 10000000) { + ErrorF("XP: BitBLT engine time-out.\n"); + count = 9990000; + timeout++; + if (timeout == 8) { + /* Reset BitBLT Engine */ + TGUI_STATUS(0x00); + return; + } + } + } +} + +static void +XPClearSync(ScrnInfoPtr pScrn) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int count = 0, timeout = 0; + int busy; + + for (;;) { + BLTBUSY(busy); + if (busy != GE_BUSY) { + return; + } + count++; + if (count == 10000000) { + ErrorF("XP: BitBLT engine time-out.\n"); + count = 9990000; + timeout++; + if (timeout == 8) { + /* Reset BitBLT Engine */ + TGUI_STATUS(0x00); + return; + } + } + } +} + +static void +XPSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int dst = 0; + + pTrident->BltScanDirection = 0; + if (xdir < 0) pTrident->BltScanDirection |= XNEG; + if (ydir < 0) pTrident->BltScanDirection |= YNEG; + + REPLICATE(transparency_color); + if (transparency_color != -1) { + dst |= 3<<16; + MMIO_OUT32(pTrident->IOBase, 0x2134, transparency_color); + } + + TGUI_DRAWFLAG(pTrident->BltScanDirection | SCR2SCR | dst); + TGUI_FMIX(XAACopyROP[rop]); +} + +static void +XPSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + if (pTrident->BltScanDirection & YNEG) { + y1 = y1 + h - 1; + y2 = y2 + h - 1; + } + if (pTrident->BltScanDirection & XNEG) { + x1 = x1 + w - 1; + x2 = x2 + w - 1; + } + XP_SRC_XY(x1,y1); + XP_DEST_XY(x2,y2); + XP_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + XPClearSync(pScrn); +} + +#if 0 +static void +XPSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + pTrident->BltScanDirection = 0; + REPLICATE(color); + TGUI_FMIX(XAAPatternROP[rop]); + if (pTrident->Chipset >= PROVIDIA9685) { + TGUI_FPATCOL(color); + } else { + TGUI_FCOLOUR(color); + } +} + +static void +XPSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp = pTrident->BltScanDirection; + + if (octant & YMAJOR) tmp |= YMAJ; + if (octant & XDECREASING) tmp |= XNEG; + if (octant & YDECREASING) tmp |= YNEG; + TGUI_DRAWFLAG(SOLIDFILL | STENCIL | tmp); + XP_SRC_XY(dmin-dmaj,dmin); + XP_DEST_XY(x,y); + XP_DIM_XY(dmin+e,len); + TGUI_COMMAND(GE_BRESLINE); + XPSync(pScrn); +} +#endif + +static void +XPSubsequentSolidHorVertLine( + ScrnInfoPtr pScrn, + int x, int y, + int len, int dir +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_DRAWFLAG(SOLIDFILL); + if (dir == DEGREES_0) { + XP_DIM_XY(len,1); + XP_DEST_XY(x,y); + } else { + XP_DIM_XY(1,len); + XP_DEST_XY(x,y); + } + TGUI_COMMAND(GE_BLT); + XPSync(pScrn); +} + +#if 0 +void +XPSetupForDashedLine( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int length, + unsigned char *pattern +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + CARD32 *DashPattern = (CARD32*)pattern; + CARD32 NiceDashPattern = DashPattern[0]; + + NiceDashPattern = *((CARD16 *)pattern) & ((1<<length) - 1); + switch(length) { + case 2: NiceDashPattern |= NiceDashPattern << 2; + case 4: NiceDashPattern |= NiceDashPattern << 4; + case 8: NiceDashPattern |= NiceDashPattern << 8; + } + pTrident->BltScanDirection = 0; + REPLICATE(fg); + if (pTrident->Chipset >= PROVIDIA9685) { + TGUI_FPATCOL(fg); + if (bg == -1) { + pTrident->BltScanDirection |= 1<<12; + TGUI_BPATCOL(~fg); + } else { + REPLICATE(bg); + TGUI_BPATCOL(bg); + } + } else { + TGUI_FCOLOUR(fg); + if (bg == -1) { + pTrident->BltScanDirection |= 1<<12; + TGUI_BCOLOUR(~fg); + } else { + REPLICATE(bg); + TGUI_BCOLOUR(bg); + } + } + TGUI_FMIX(XAAPatternROP[rop]); + pTrident->LinePattern = NiceDashPattern; +} + +void +XPSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int tmp = pTrident->BltScanDirection; + + if (octant & YMAJOR) tmp |= YMAJ; + if (octant & XDECREASING) tmp |= XNEG; + if (octant & YDECREASING) tmp |= YNEG; + + TGUI_STYLE(((pTrident->LinePattern >> phase) | + (pTrident->LinePattern << (16-phase))) & 0x0000FFFF); + TGUI_DRAWFLAG(STENCIL | tmp); + XP_SRC_XY(dmin-dmaj,dmin); + XP_DEST_XY(x,y); + XP_DIM_XY(e+dmin,len); + TGUI_COMMAND(GE_BRESLINE); + XPSync(pScrn); +} +#endif + +static void +XPSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + REPLICATE(color); + TGUI_FMIX(XAAPatternROP[rop]); + MMIO_OUT32(pTrident->IOBase, 0x2158, color); + TGUI_DRAWFLAG(SOLIDFILL); +} + +static void +XPSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + XP_DIM_XY(w,h); + XP_DEST_XY(x,y); + TGUI_COMMAND(GE_BLT); + XPSync(pScrn); +} + +#if 0 +static void MoveDWORDS( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + if (!dwords) return; + *dest = *src; + dest += 1; + src += 1; + if (dwords == 1) return; + *dest = *src; + dest += 1; + src += 1; + if (dwords == 2) return; + *dest = *src; + dest += 1; + src += 1; +} +#endif + +#if 0 +static void MoveDWORDS_FixedBase( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *dest = *(src + 1); + *dest = *(src + 2); + *dest = *(src + 3); + dwords -= 4; + src += 4; + } + + if(!dwords) return; + *dest = *src; + if(dwords == 1) return; + *dest = *(src + 1); + if(dwords == 2) return; + *dest = *(src + 2); +} +#endif + + +static void +XPSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, + int fg, int bg, int rop, + unsigned int planemask) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + int drawflag = 0; + + REPLICATE(fg); + MMIO_OUT32(pTrident->IOBase, 0x2158, fg); + + if (bg == -1) { + drawflag |= 1<<12; + MMIO_OUT32(pTrident->IOBase, 0x215C, ~fg); + } else { + REPLICATE(bg); + MMIO_OUT32(pTrident->IOBase, 0x215C, bg); + } + + drawflag |= 7<<18; + TGUI_DRAWFLAG(PATMONO | drawflag); + MMIO_OUT32(pTrident->IOBase, 0x2180, patternx); + MMIO_OUT32(pTrident->IOBase, 0x2184, patterny); + TGUI_FMIX(XAAPatternROP[rop]); +} + +static void +XPSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, + int w, int h) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + XP_DEST_XY(x,y); + XP_DIM_XY(w,h); + TGUI_COMMAND(GE_BLT); + XPSync(pScrn); +} + +#if 0 +static void +XPSetupForScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + + TGUI_FMIX(XAACopyROP[rop]); + if (bg == -1) { + TGUI_DRAWFLAG(SRCMONO | 1<<12); + REPLICATE(fg); + TGUI_FCOLOUR(fg); + } else { + TGUI_DRAWFLAG(SRCMONO); + REPLICATE(fg); + REPLICATE(bg); + TGUI_FCOLOUR(fg); + TGUI_BCOLOUR(bg); + } +} + +static void +XPSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft +){ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + pTrident->dwords = (w + 31) >> 5; + pTrident->h = h; + + XP_DEST_XY(x,y); + XP_DIM_XY(w>>1,h); + TGUI_COMMAND(GE_BLT); +} + +static void +XPSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + TRIDENTPtr pTrident = TRIDENTPTR(pScrn); + XAAInfoRecPtr infoRec; + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + MoveDWORDS_FixedBase((CARD32 *)pTrident->IOBase + 0x2160, + (CARD32 *)pTrident->XAAScanlineColorExpandBuffers[0], + pTrident->dwords); + + pTrident->h--; + if (pTrident->h) + XPSync(pScrn); +} +#endif |