850 lines
24 KiB
C
850 lines
24 KiB
C
/*
|
|
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
|
|
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
|
|
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
|
|
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
|
|
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
|
|
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
|
|
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
|
|
**
|
|
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
|
|
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
|
|
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
|
|
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
|
|
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
|
|
** THE UNITED STATES.
|
|
**
|
|
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
We need to provide the following functions:
|
|
|
|
char *
|
|
hwcGetErrorString(void);
|
|
|
|
hwcInfo *
|
|
hwcInit(FxU32 vID, FxU32 dID);
|
|
|
|
FxBool
|
|
hwcMapBoard(hwcBoardInfo *bInfo, FxU32 bAddrMask);
|
|
|
|
FxBool
|
|
hwcInitRegisters(hwcBoardInfo *bInfo);
|
|
|
|
FxBool
|
|
hwcAllocBuffers(hwcBoardInfo *bInfo, FxU32 nColBuffers, FxU32 nAuxBuffers);
|
|
|
|
FxBool
|
|
hwcInitFifo(hwcBoardInfo *bInfo);
|
|
|
|
FxU32
|
|
hwcInitAGPFifo(hwcBoardInfo *bInfo);
|
|
|
|
FxBool
|
|
hwcInitVideo(hwcBoardInfo *bInfo, FxBool tiled, FxVideoTimingInfo
|
|
*vidTiming, FxBool overlay);
|
|
|
|
FxBool
|
|
hwcRestoreVideo(hwcBoardInfo *bInfo);
|
|
|
|
FxBool
|
|
hwcCheckMemSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxU32 nColBuffers,
|
|
FxU32 nAuxBuffers, FxBool tiled);
|
|
*/
|
|
|
|
#include <minihwc.h>
|
|
#include <hwcio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <X11/Xlib.h>
|
|
/*#include <X11/extensions/xf86dga.h>*/
|
|
#include <X11/extensions/xf86vmode.h>
|
|
#include "lindri.h"
|
|
|
|
void
|
|
_grInvalidateAll(void);
|
|
void
|
|
_grExportFifo(int *fifoPtr, int *fifoRead);
|
|
void
|
|
_grImportFifo(int fifoPtr, int fifoRead);
|
|
static FxU32
|
|
hwcBufferLfbAddr(const hwcBoardInfo *bInfo, FxU32 physAddress);
|
|
|
|
#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
|
|
# define __attribute_used __attribute__((__used__))
|
|
#elif defined(__GNUC__) && (__GNUC__ >= 2)
|
|
# define __attribute_used __attribute__((__unused__))
|
|
#else
|
|
# define __attribute_used
|
|
#endif
|
|
|
|
static FxU32 __attribute_used fenceVar;
|
|
#if defined(__GNUC__) && defined(__ia64__)
|
|
# define P6FENCE asm volatile ("mf.a" ::: "memory");
|
|
#elif defined(__GNUC__) && defined(__alpha__)
|
|
# define P6FENCE asm volatile("mb" ::: "memory");
|
|
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
|
# define P6FENCE asm("xchg %%eax, %0" : : "m" (fenceVar) : "eax");
|
|
#else
|
|
# error "No P6FENCE asm for this architecture"
|
|
#endif
|
|
|
|
#define MAXFIFOSIZE 0x40000
|
|
#define FIFOPAD 0x0000
|
|
#define AUXPAD 0x1000
|
|
#define HWC_TILED_BUFFER_BYTES 0x1000UL /* 128 Bytes x 32 lines */
|
|
#define HWC_TILED_BUFFER_Y_ALIGN 0x20000UL
|
|
#define HWC_TILED_BUFFER_X_ADJUST 0x80UL
|
|
|
|
static hwcInfo hInfo;
|
|
static char errorString[1024];
|
|
|
|
static FxU32 calcBufferStride(FxU32 xres, FxBool tiled);
|
|
static FxU32 calcBufferSize(FxU32 xres, FxU32 yres, FxBool tiled);
|
|
static FxU32 calcBufferSizeInTiles(FxU32 xres, FxU32 yres);
|
|
static FxU32 calcBufferHeightInTiles(FxU32 yres);
|
|
|
|
typedef struct envitem_t {
|
|
char *env;
|
|
char *val;
|
|
struct envitem_t *next;
|
|
} envitem;
|
|
|
|
static envitem *first=0;
|
|
static int envinit=0;
|
|
|
|
DRIDef driInfo={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
|
|
|
void grDRIOpen(char *pFB, char *pRegs, int deviceID, int width, int height,
|
|
int mem, int cpp, int stride, int fifoOffset, int fifoSize,
|
|
int fbOffset, int backOffset, int depthOffset,
|
|
int textureOffset, int textureSize,
|
|
volatile int *fifoPtr, volatile int *fifoRead) {
|
|
driInfo.pFB=pFB;
|
|
driInfo.pRegs=pRegs;
|
|
driInfo.deviceID=deviceID;
|
|
driInfo.screenWidth=width;
|
|
driInfo.screenHeight=height;
|
|
driInfo.memory=mem;
|
|
driInfo.cpp=cpp;
|
|
driInfo.stride=stride;
|
|
driInfo.fifoOffset=fifoOffset;
|
|
driInfo.fifoSize = fifoSize;
|
|
driInfo.fbOffset=fbOffset;
|
|
driInfo.backOffset=backOffset;
|
|
driInfo.depthOffset=depthOffset;
|
|
driInfo.textureOffset=textureOffset;
|
|
driInfo.textureSize=textureSize;
|
|
driInfo.fifoPtr=fifoPtr;
|
|
driInfo.fifoRead=fifoRead;
|
|
}
|
|
|
|
void grDRIPosition(int x, int y, int w, int h,
|
|
int numClip, XF86DRIClipRectPtr pClip) {
|
|
driInfo.x=x;
|
|
driInfo.y=y;
|
|
driInfo.w=w;
|
|
driInfo.h=h;
|
|
driInfo.numClip=numClip;
|
|
driInfo.pClip=pClip;
|
|
}
|
|
|
|
static void loadEnvFile() {
|
|
FILE *file;
|
|
char data[128];
|
|
char *env, *val;
|
|
envitem *item;
|
|
int is_first=1;
|
|
|
|
if (envinit) return;
|
|
envinit=1;
|
|
file=fopen("/etc/conf.3dfx/voodoo3", "r");
|
|
if (!file) return;
|
|
while (1) {
|
|
if (!fgets(data, 128, file)) return;
|
|
if (*data=='#') continue;
|
|
if (*data=='\n') continue;
|
|
val=strchr(data, '=');
|
|
if (!val) {
|
|
if (is_first) {
|
|
fprintf(stderr, "In config file /etc/conf.3dfx/voodoo3:\n");
|
|
is_first=0;
|
|
}
|
|
fprintf(stderr, "Malformed line: %s\n", data);
|
|
continue;
|
|
}
|
|
*val=0;
|
|
env=data;
|
|
val++;
|
|
item=malloc(sizeof(envitem));
|
|
item->env=malloc(strlen(env)+1);
|
|
strcpy(item->env, env);
|
|
item->val=malloc(strlen(val)+1);
|
|
strcpy(item->val, val);
|
|
item->next=first;
|
|
first=item;
|
|
}
|
|
}
|
|
|
|
#if 0 /* not used */
|
|
static void deleteEnvData() {
|
|
envitem *ptr, *next;
|
|
|
|
ptr=first;
|
|
while (ptr) {
|
|
next=ptr->next;
|
|
if (ptr->env) free(ptr->env);
|
|
if (ptr->val) free(ptr->val);
|
|
free(ptr);
|
|
ptr=next;
|
|
}
|
|
first=0;
|
|
envinit=0;
|
|
}
|
|
#endif
|
|
|
|
char *
|
|
hwcGetErrorString()
|
|
{
|
|
#define FN_NAME "hwcGetErrorString"
|
|
return errorString;
|
|
#undef FN_NAME
|
|
} /* hwcGetErrorString */
|
|
|
|
hwcInfo *
|
|
hwcInit(FxU32 vID, FxU32 dID) {
|
|
hInfo.nBoards = 0;
|
|
|
|
errorString[0] = '\0';
|
|
|
|
if (!driInfo.pFB) return 0;
|
|
if (dID!=(FxU32)driInfo.deviceID) return 0;
|
|
hInfo.boardInfo[0].pciInfo.initialized = FXFALSE;
|
|
hInfo.nBoards++;
|
|
hInfo.boardInfo[0].boardNum = 0;
|
|
|
|
hInfo.boardInfo[0].pciInfo.initialized = FXTRUE;;
|
|
hInfo.boardInfo[0].pciInfo.vendorID = vID;
|
|
hInfo.boardInfo[0].pciInfo.deviceID = dID;
|
|
hInfo.boardInfo[0].h3Mem = driInfo.memory>>20;
|
|
if (hInfo.nBoards) {
|
|
return &hInfo;
|
|
} else {
|
|
sprintf(errorString, "Can't find or access Banshee/V3 board\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
FxBool
|
|
hwcMapBoard(hwcBoardInfo *bInfo, FxU32 bAddrMask) {
|
|
if (bInfo->pciInfo.initialized == FXFALSE) {
|
|
sprintf(errorString, "hwcMapBoard: Called before hwcInit\n");
|
|
return FXFALSE;
|
|
}
|
|
|
|
bInfo->linearInfo.initialized = FXTRUE;
|
|
bInfo->linearInfo.linearAddress[0]=(unsigned long)driInfo.pRegs;
|
|
bInfo->linearInfo.linearAddress[1]=(unsigned long)driInfo.pFB;
|
|
return FXTRUE;
|
|
}
|
|
|
|
FxBool
|
|
hwcUnmapBoard(hwcBoardInfo *bInfo) {
|
|
return FXTRUE;
|
|
}
|
|
|
|
FxBool
|
|
hwcInitRegisters(hwcBoardInfo *bInfo) {
|
|
int dramInit1;
|
|
|
|
if (bInfo->linearInfo.initialized == FXFALSE) {
|
|
printf(errorString, "hwcInitRegisters Called before hwcMapBoard\n");
|
|
return FXFALSE;
|
|
}
|
|
|
|
bInfo->regInfo.initialized = FXTRUE;
|
|
|
|
bInfo->regInfo.ioMemBase =
|
|
bInfo->linearInfo.linearAddress[0] + SST_IO_OFFSET;
|
|
bInfo->regInfo.cmdAGPBase =
|
|
bInfo->linearInfo.linearAddress[0] + SST_CMDAGP_OFFSET;
|
|
bInfo->regInfo.waxBase =
|
|
bInfo->linearInfo.linearAddress[0] + SST_2D_OFFSET;
|
|
bInfo->regInfo.sstBase =
|
|
bInfo->linearInfo.linearAddress[0] + SST_3D_OFFSET;
|
|
bInfo->regInfo.lfbBase =
|
|
bInfo->linearInfo.linearAddress[0] + SST_LFB_OFFSET;
|
|
bInfo->regInfo.rawLfbBase =
|
|
bInfo->linearInfo.linearAddress[1];
|
|
bInfo->regInfo.ioPortBase = (FxU16) bInfo->pciInfo.pciBaseAddr[2] & ~0x1;
|
|
|
|
/* Figure out if it's SDRAM */
|
|
HWC_IO_LOAD(bInfo->regInfo, dramInit1, dramInit1);
|
|
dramInit1 &= SST_MCTL_TYPE_SDRAM;
|
|
if ( dramInit1 & SST_MCTL_TYPE_SDRAM )
|
|
bInfo->sdRAM = FXTRUE;
|
|
else
|
|
bInfo->sdRAM = FXFALSE;
|
|
|
|
{
|
|
FxU32
|
|
pciInit0,
|
|
pciCommandReg =
|
|
BIT(0) | /* enable i/o decode */
|
|
BIT(1); /* enable memory decode */
|
|
|
|
/* Enable PCI memory and I/O decode */
|
|
pciSetConfigData(PCI_COMMAND, bInfo->deviceNum, &pciCommandReg);
|
|
|
|
HWC_IO_LOAD(bInfo->regInfo, pciInit0, pciInit0);
|
|
pciInit0 |= SST_PCI_READ_WS | SST_PCI_WRITE_WS;
|
|
HWC_IO_STORE(bInfo->regInfo, pciInit0, pciInit0);
|
|
}
|
|
|
|
return FXTRUE;
|
|
}
|
|
|
|
FxBool
|
|
hwcAllocBuffers(hwcBoardInfo *bInfo, FxU32 nColBuffers, FxU32 nAuxBuffers)
|
|
{
|
|
#define FN_NAME "hwcAllocBuffers"
|
|
FxU32 bufStride, bufSize;
|
|
|
|
if (bInfo->vidInfo.initialized == FXFALSE) {
|
|
sprintf(errorString, "%s: Called before video initialization\n", FN_NAME);
|
|
return FXFALSE;
|
|
}
|
|
|
|
GDBG_INFO(80, "%s(0x%x, 0x%x, 0x%x)\n", FN_NAME, bInfo, nColBuffers, nAuxBuffers);
|
|
|
|
/* I've decided on > 2 instead of == 3 because we may support more
|
|
than 3 buffers in the future, and want 4 to set the
|
|
triple-buffering bit in dramInit1, also */
|
|
bInfo->vidInfo.tripleBuffering = (nColBuffers > 2);
|
|
|
|
bInfo->vidInfo.stride = bufStride =
|
|
calcBufferStride(driInfo.screenWidth, bInfo->vidInfo.tiled);
|
|
|
|
/* We want to place the FIFO after the tram but before the color
|
|
buffers with some pad */
|
|
bufSize = calcBufferSize(driInfo.screenWidth, driInfo.screenHeight,
|
|
bInfo->vidInfo.tiled);
|
|
|
|
bInfo->buffInfo.bufStride = bufStride;
|
|
bInfo->buffInfo.bufSize = bufSize;
|
|
|
|
if (bInfo->vidInfo.tiled) {
|
|
bInfo->buffInfo.bufStrideInTiles = (bufStride >> 7);
|
|
bInfo->buffInfo.bufSizeInTiles =
|
|
calcBufferSizeInTiles(driInfo.screenWidth, driInfo.screenHeight);
|
|
bInfo->buffInfo.bufHeightInTiles =
|
|
calcBufferHeightInTiles(driInfo.screenHeight);
|
|
}
|
|
|
|
bInfo->buffInfo.initialized = FXTRUE;
|
|
bInfo->buffInfo.nColBuffers = nColBuffers;
|
|
bInfo->buffInfo.nAuxBuffers = nAuxBuffers;
|
|
|
|
bInfo->fbOffset = driInfo.fbOffset;
|
|
|
|
bInfo->fifoInfo.fifoStart = driInfo.fifoOffset;
|
|
bInfo->fifoInfo.fifoLength = driInfo.fifoSize;
|
|
|
|
bInfo->tramOffset = driInfo.textureOffset;
|
|
bInfo->tramSize = driInfo.textureSize;
|
|
|
|
bInfo->buffInfo.colBuffStart[0] = driInfo.fbOffset;
|
|
bInfo->buffInfo.colBuffEnd[0] = driInfo.fbOffset +
|
|
driInfo.screenHeight*driInfo.stride;
|
|
|
|
bInfo->buffInfo.colBuffStart[1] = driInfo.backOffset;
|
|
bInfo->buffInfo.colBuffEnd[1] = driInfo.backOffset+bufSize;
|
|
|
|
bInfo->buffInfo.auxBuffStart = driInfo.depthOffset;
|
|
bInfo->buffInfo.auxBuffEnd = driInfo.depthOffset+bufSize;
|
|
|
|
bInfo->buffInfo.lfbBuffAddr[0] = bInfo->buffInfo.colBuffStart[0];
|
|
bInfo->buffInfo.lfbBuffAddr[1] = bInfo->buffInfo.colBuffStart[1];
|
|
if (bInfo->vidInfo.tiled) {
|
|
bInfo->buffInfo.lfbBuffAddr[2] =
|
|
hwcBufferLfbAddr(bInfo, bInfo->buffInfo.auxBuffStart);
|
|
} else {
|
|
bInfo->buffInfo.lfbBuffAddr[2] = bInfo->buffInfo.auxBuffStart;
|
|
}
|
|
|
|
GDBG_INFO(80, "%s: Board Info:\n", FN_NAME);
|
|
GDBG_INFO(80, "\thdc: 0x%x\n", bInfo->hdc);
|
|
GDBG_INFO(80, "\textContextID: 0x%x\n", bInfo->extContextID);
|
|
GDBG_INFO(80, "\tdevRev: 0x%x\n", bInfo->devRev);
|
|
GDBG_INFO(80, "\tfbOffset: 0x%x\n", bInfo->fbOffset);
|
|
GDBG_INFO(80, "\th3Rev: 0x%x\n", bInfo->h3Rev);
|
|
GDBG_INFO(80, "\th3Mem: 0x%x\n", bInfo->h3Mem);
|
|
GDBG_INFO(80, "\tboardNum: 0x%x\n", bInfo->boardNum);
|
|
GDBG_INFO(80, "\tdeviceNum: 0x%x\n", bInfo->deviceNum);
|
|
|
|
GDBG_INFO(80, "%s: Buffer Info:\n", FN_NAME);
|
|
GDBG_INFO(80, "\tbufSize: 0x%x\n", bInfo->buffInfo.bufSize);
|
|
GDBG_INFO(80, "\tbufSizeInTiles: 0x%x\n", bInfo->buffInfo.bufSizeInTiles);
|
|
GDBG_INFO(80, "\tbufStride: 0x%x\n", bInfo->buffInfo.bufStride);
|
|
GDBG_INFO(80, "\tbufStrideInTiles:0x%x\n", bInfo->buffInfo.bufStrideInTiles);
|
|
GDBG_INFO(80, "\tbufHeightInTiles:0x%x\n", bInfo->buffInfo.bufHeightInTiles);
|
|
GDBG_INFO(80, "\tnColBuffers: 0x%x\n", bInfo->buffInfo.nColBuffers);
|
|
GDBG_INFO(80, "\tcolBuffStart[0]: 0x%x\n", bInfo->buffInfo.colBuffStart[0]);
|
|
GDBG_INFO(80, "\tcolBuffEnd[0]: 0x%x\n", bInfo->buffInfo.colBuffEnd[0]);
|
|
GDBG_INFO(80, "\tcolBuffStart[1]: 0x%x\n", bInfo->buffInfo.colBuffStart[1]);
|
|
GDBG_INFO(80, "\tcolBuffEnd[1]: 0x%x\n", bInfo->buffInfo.colBuffEnd[1]);
|
|
GDBG_INFO(80, "\tnAuxBuffers: 0x%x\n", bInfo->buffInfo.nAuxBuffers);
|
|
GDBG_INFO(80, "\tauxBuffStart: 0x%x\n", bInfo->buffInfo.auxBuffStart);
|
|
GDBG_INFO(80, "\tauxBuffEnd: 0x%x\n", bInfo->buffInfo.auxBuffEnd);
|
|
GDBG_INFO(80, "\ttramOffset: 0x%x\n", bInfo->tramOffset);
|
|
GDBG_INFO(80, "\ttramSize: 0x%x\n", bInfo->tramSize);
|
|
GDBG_INFO(80, "\tlfbBuffAddr[0] 0x%x\n", bInfo->buffInfo.lfbBuffAddr[0]);
|
|
GDBG_INFO(80, "\tlfbBuffAddr[1] 0x%x\n", bInfo->buffInfo.lfbBuffAddr[1]);
|
|
GDBG_INFO(80, "\tlfbBuffAddr[2] 0x%x\n", bInfo->buffInfo.lfbBuffAddr[2]);
|
|
|
|
GDBG_INFO(80, "%s: FIFO Info:\n", FN_NAME);
|
|
GDBG_INFO(80, "\tfifoStart: 0x%x\n", bInfo->fifoInfo.fifoStart);
|
|
GDBG_INFO(80, "\tfifoLength: 0x%x\n", bInfo->fifoInfo.fifoLength);
|
|
return FXTRUE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcAllocBuffers */
|
|
|
|
FxBool
|
|
hwcInitFifo(hwcBoardInfo *bInfo, FxBool enableHoleCounting)
|
|
{
|
|
#define FN_NAME "hwcInitFifo"
|
|
if (bInfo->regInfo.initialized == FXFALSE) {
|
|
sprintf(errorString, "%s: Called before hwcMapBoard\n", FN_NAME);
|
|
return FXFALSE;
|
|
}
|
|
|
|
if (bInfo->buffInfo.initialized == FXFALSE) {
|
|
sprintf(errorString, "%s: Called before hwcInitBuffers\n", FN_NAME);
|
|
return FXFALSE;
|
|
}
|
|
|
|
#if 0
|
|
driInfo.holeCounting=enableHoleCounting;
|
|
hwcInitFifoRegs(enableHoleCounting);
|
|
#endif
|
|
|
|
GDBG_INFO(80 ,"%s: CMD FIFO placed at physical addr 0x%x size 0x%0x\n",
|
|
FN_NAME, driInfo.fifoOffset, driInfo.fifoSize);
|
|
|
|
return FXTRUE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcInitFifo */
|
|
|
|
FxBool
|
|
hwcInitVideo(hwcBoardInfo *bInfo, FxBool tiled, FxVideoTimingInfo
|
|
*vidTiming, FxBool overlay) {
|
|
FxU32 stride, dramInit1, miscInit0;
|
|
|
|
stride= (tiled) ? bInfo->buffInfo.bufStrideInTiles : bInfo->vidInfo.stride;
|
|
|
|
/* Video pixel buffer threshold */
|
|
{
|
|
FxU32 vidPixelBufThold;
|
|
FxU32 thold = 32;
|
|
|
|
if (getenv("SSTVB_PIXTHOLD")) {
|
|
thold = atoi(getenv("SSTVB_PIXTHOLD"));
|
|
}
|
|
|
|
thold &= 0x3f;
|
|
|
|
vidPixelBufThold = (thold | (thold << 6) | (thold << 12));
|
|
|
|
HWC_IO_STORE(bInfo->regInfo, vidPixelBufThold, vidPixelBufThold);
|
|
}
|
|
|
|
/* Check to see if the screen and overlay dimensions match.
|
|
* There are two cases that can happen in reality.
|
|
*
|
|
* scrXXX > appXXX: This is a 'real' case, and the overlay dimension
|
|
* needs to mag scaled so that it fits the requested size.
|
|
*
|
|
* (scrXXX == appXXX) && (ovlXXX != scrXXX): This is a somewhat artificial
|
|
* case where someone left the overlay set to some value, and these did
|
|
* not get reset in the setVideoMode processing. (For example, if the user is
|
|
* running an application which bus masters data directly to our video overlay
|
|
* when launching a glide application). In this case we need to fiddle w/ the
|
|
* overlay dimension so that it matches the requested resolution.
|
|
*
|
|
* (scrXXX < appXXX): If setVideoMode is actually working correctly, this cannot
|
|
* happen because that code has to know that we can't do min scaling.
|
|
*/
|
|
|
|
/* Get miscInit0 for y-sub */
|
|
HWC_IO_LOAD(bInfo->regInfo, miscInit0, miscInit0);
|
|
|
|
/* Clear out relavent bits */
|
|
miscInit0 &= ~SST_YORIGIN_TOP;
|
|
miscInit0 |= ((driInfo.screenHeight - 1) << SST_YORIGIN_TOP_SHIFT);
|
|
HWC_IO_STORE(bInfo->regInfo, miscInit0, miscInit0);
|
|
|
|
/* Set up dramInit1 for triple or double buffering */
|
|
HWC_IO_LOAD(bInfo->regInfo, dramInit1, dramInit1);
|
|
if (bInfo->vidInfo.tripleBuffering)
|
|
dramInit1 |= SST_TRIPLE_BUFFER_EN;
|
|
else
|
|
dramInit1 &= ~SST_TRIPLE_BUFFER_EN;
|
|
HWC_IO_STORE(bInfo->regInfo, dramInit1, dramInit1);
|
|
|
|
HWC_IO_STORE(bInfo->regInfo, vidMaxRGBDelta, 0x100810);
|
|
|
|
return FXTRUE;
|
|
}
|
|
|
|
FxBool
|
|
hwcRestoreVideo(hwcBoardInfo *bInfo) {
|
|
return FXTRUE;
|
|
}
|
|
|
|
static FxU32
|
|
calcBufferStride(FxU32 xres, FxBool tiled)
|
|
{
|
|
FxU32
|
|
strideInTiles;
|
|
|
|
if (tiled == FXTRUE) {
|
|
/* Calculate tile width stuff */
|
|
strideInTiles = (xres << 1) >> 7;
|
|
if ((xres << 1) & (HWC_TILE_WIDTH - 1))
|
|
strideInTiles++;
|
|
|
|
return (strideInTiles * HWC_TILE_WIDTH);
|
|
|
|
} else {
|
|
return (xres << 1);
|
|
}
|
|
} /* calcBufferStride */
|
|
|
|
static FxU32
|
|
calcBufferHeightInTiles(FxU32 yres)
|
|
{
|
|
FxU32
|
|
heightInTiles; /* Height of buffer in tiles */
|
|
|
|
|
|
/* Calculate tile height stuff */
|
|
heightInTiles = yres >> 5;
|
|
|
|
if (yres & (HWC_TILE_HEIGHT - 1))
|
|
heightInTiles++;
|
|
|
|
return heightInTiles;
|
|
|
|
} /* calcBufferHeightInTiles */
|
|
|
|
static FxU32
|
|
calcBufferSizeInTiles(FxU32 xres, FxU32 yres) {
|
|
FxU32
|
|
bufSizeInTiles; /* Size of buffer in tiles */
|
|
|
|
bufSizeInTiles =
|
|
calcBufferHeightInTiles(yres) * (calcBufferStride(xres, FXTRUE) >> 7);
|
|
|
|
return bufSizeInTiles;
|
|
|
|
} /* calcBufferSizeInTiles */
|
|
|
|
static FxU32
|
|
calcBufferSize(FxU32 xres, FxU32 yres, FxBool tiled)
|
|
{
|
|
FxU32
|
|
stride,
|
|
height,
|
|
bufSize; /* Size of buffer in bytes */
|
|
|
|
if (tiled) {
|
|
stride = calcBufferStride(xres, tiled);
|
|
height = HWC_TILE_HEIGHT * calcBufferHeightInTiles(yres);
|
|
} else {
|
|
stride = xres << 1;
|
|
height = yres;
|
|
}
|
|
|
|
bufSize = stride * height;
|
|
|
|
return bufSize;
|
|
|
|
} /* calcBufferSize */
|
|
|
|
FxBool
|
|
hwcCheckMemSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxU32 nColBuffers,
|
|
FxU32 nAuxBuffers, FxBool tiled)
|
|
{
|
|
#define FN_NAME "hwcCheckMemSize"
|
|
FxU32
|
|
bufSize, totSize;
|
|
|
|
bufSize = calcBufferSize(xres, yres, tiled);
|
|
|
|
totSize = (nColBuffers + nAuxBuffers) * bufSize;
|
|
|
|
if (totSize < ((bInfo->h3Mem << 20) - 0x200000)) /* Need 2M for texture */
|
|
return FXTRUE;
|
|
else
|
|
return FXFALSE;
|
|
#undef FN_NAME
|
|
} /* hwcCheckMemSize */
|
|
|
|
/* How the hw treats lfb accesses are dependent on the 'type' of
|
|
* memory (tiled/linear) that the color/aux buffers are in. We
|
|
* pre-compute the actual lfb address here while we know about the
|
|
* memory space and if we adjusted the page alignment above.
|
|
*
|
|
* NB: If we are in tiled mode then the fact that we align the color
|
|
* buffers on page boundaries means that the y offset of the buffers
|
|
* may not actually be on a boundary for the tile addressing scheme.
|
|
* The 'rounding' done to HWC_TILED_BUFFER_Y_ALIGN adjust for this.
|
|
*
|
|
* NB: The memory optimization of aligning color buffers on even page
|
|
* boundaries will cause the tiled lfb access to be off by a page so
|
|
* we add in the width of a page (HWC_TILED_BUFFER_X_ADJUST) here.
|
|
*/
|
|
static FxU32
|
|
hwcBufferLfbAddr(const hwcBoardInfo *bInfo, FxU32 physAddress)
|
|
{
|
|
FxU32 retVal = 0x00UL;
|
|
|
|
FxU32 tileAddress;
|
|
FxU32 tileNumber;
|
|
FxU32 tileOffset;
|
|
FxU32 tileXOffset;
|
|
FxU32 tileScanline;
|
|
FxU32 tileRow;
|
|
FxU32 lfbAddress;
|
|
FxU32 lfbYOffset;
|
|
/*
|
|
* This is the tile aperture stride. It is always 4096 for V3.
|
|
*/
|
|
FxU32 lfbBufferStride = 0x1000;
|
|
|
|
if (bInfo->vidInfo.tiled) {
|
|
GDBG_INFO(80, "\tphysAddress: 0x%08lx\n",physAddress);
|
|
|
|
/* Compute address in tile space */
|
|
tileAddress = physAddress - driInfo.backOffset;
|
|
GDBG_INFO(80, "\ttileAddress: 0x%08lx\n",tileAddress);
|
|
|
|
/* Compute tile number we're in (each tile is 4K bytes) */
|
|
tileNumber = tileAddress >> 12;
|
|
GDBG_INFO(80, "\ttileNumber: 0x%08lx (%d)\n",tileNumber,tileNumber);
|
|
|
|
/* Compute base tile row we're in */
|
|
tileRow = tileNumber / bInfo->buffInfo.bufStrideInTiles;
|
|
GDBG_INFO(80, "\ttileRow: %d (stride = %d)\n",tileNumber,bInfo->buffInfo.bufStrideInTiles);
|
|
|
|
/* Compute offset within the tile */
|
|
tileOffset = tileAddress - (tileNumber << 12);
|
|
GDBG_INFO(80, "\ttileOffset: 0x%08lx\n",tileOffset);
|
|
|
|
/* Compute scanline within the tile */
|
|
tileScanline = tileOffset >> 7;
|
|
GDBG_INFO(80, "\ttileScanline: 0x%08lx\n",tileScanline);
|
|
|
|
/* Compute tile X offset within the row */
|
|
tileXOffset = tileNumber - (tileRow * bInfo->buffInfo.bufStrideInTiles);
|
|
GDBG_INFO(80, "\ttileXOffset: %d\n",tileXOffset);
|
|
|
|
/* Compute Y offset in LFB space */
|
|
lfbYOffset = (tileRow * 32 + tileScanline);
|
|
|
|
/* Compute LFB address of tile start */
|
|
lfbAddress = driInfo.backOffset + lfbYOffset * lfbBufferStride + tileXOffset * 128;
|
|
|
|
GDBG_INFO(80, "\tlfbAddress: %08lx\n", lfbAddress);
|
|
retVal = lfbAddress;
|
|
} else {
|
|
retVal = physAddress;
|
|
}
|
|
return retVal;
|
|
}
|
|
FxU32
|
|
hwcInitAGPFifo(hwcBoardInfo *bInfo, FxBool enableHoleCounting)
|
|
{
|
|
return hwcInitFifo(bInfo, enableHoleCounting);
|
|
}
|
|
|
|
#define RED_SHIFT 16
|
|
#define GREEN_SHIFT 8
|
|
#define BLUE_SHIFT 0
|
|
|
|
FxBool
|
|
hwcGammaTable(hwcBoardInfo *bInfo, FxU32 nEntries, FxU32 *r, FxU32 *g, FxU32 *b)
|
|
{
|
|
#define FN_NAME "hwcGammaTable"
|
|
FxU32 gRamp[256];
|
|
FxU32 i;
|
|
FxU32 dacBase;
|
|
FxU32 rDacBase;
|
|
FxU32 rDacData;
|
|
|
|
/* Load the table into the Display driver as above */
|
|
for (i = 0; i < nEntries; i++) {
|
|
gRamp[i] =
|
|
((r[i] & 0xff) << RED_SHIFT) |
|
|
((g[i] & 0xff) << GREEN_SHIFT) |
|
|
((b[i] & 0xff) << BLUE_SHIFT);
|
|
}
|
|
|
|
dacBase = 0;
|
|
|
|
for (i = 0; i < nEntries; i++) {
|
|
int repeat = 100;
|
|
do {
|
|
HWC_IO_STORE( bInfo->regInfo, dacAddr, dacBase + i);
|
|
P6FENCE;
|
|
HWC_IO_LOAD( bInfo->regInfo, dacAddr, rDacBase);
|
|
P6FENCE;
|
|
repeat--;
|
|
} while (repeat && rDacBase != dacBase + i);
|
|
if (!repeat) {
|
|
GDBG_INFO(0, "%s:Error Writting DacAddr %d. DacBase =%d\n",
|
|
FN_NAME, dacBase+i, dacBase);
|
|
}
|
|
repeat = 100;
|
|
do {
|
|
HWC_IO_STORE( bInfo->regInfo, dacData, gRamp[i]);
|
|
P6FENCE;
|
|
HWC_IO_LOAD( bInfo->regInfo, dacData, rDacData);
|
|
P6FENCE;
|
|
repeat--;
|
|
} while (repeat && rDacData != gRamp[i]);
|
|
if (!repeat) {
|
|
GDBG_INFO(0, "%s:Error Writting Data [%d, %x]. DacBase =%d\n",
|
|
FN_NAME, i, gRamp[i], dacBase);
|
|
}
|
|
}
|
|
|
|
return FXTRUE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcGammaTable */
|
|
|
|
FxBool
|
|
hwcGammaRGB(hwcBoardInfo *bInfo, float gammaR, float gammaG, float gammaB)
|
|
{
|
|
#define FN_NAME "hwcGammaRGB"
|
|
FxU32
|
|
grRamp[256], ggRamp[256], gbRamp[256];
|
|
int
|
|
i;
|
|
|
|
GDBG_INFO(80, FN_NAME "(0x%x, %1.2f, %1.2f, %1.2f)\n",
|
|
bInfo, gammaR, gammaG, gammaB);
|
|
|
|
/*
|
|
** NB: The system eventually devised by Bob and Ken *may* require
|
|
** separate R, G, and B vectors.
|
|
*/
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
grRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F);
|
|
ggRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F);
|
|
gbRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F);
|
|
}
|
|
|
|
|
|
hwcGammaTable(bInfo, 256, grRamp, ggRamp, gbRamp);
|
|
|
|
/*
|
|
** Now that we have a gamma table, we can give it to the driver via
|
|
** a call to ExtEscape() when that is defined.....
|
|
*/
|
|
|
|
return FXFALSE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcGammaRGB */
|
|
|
|
#define M 1
|
|
#define K 1
|
|
|
|
FxBool
|
|
hwcSetGrxClock(hwcBoardInfo *bInfo, FxU32 speedInMHz)
|
|
{
|
|
#define FN_NAME "hwcSetGrxClock"
|
|
FxU32
|
|
pllCtrl1,
|
|
dramInit0 = 0xc17ae29,
|
|
dramInit1 = 0x26c031,
|
|
n,
|
|
m = 1;
|
|
|
|
n = (FxU32) ((speedInMHz - 4.76f)/2.38f);
|
|
|
|
pllCtrl1 =
|
|
(K << SST_PLL_K_SHIFT) | (m << SST_PLL_M_SHIFT) | (n << SST_PLL_N_SHIFT);
|
|
|
|
GDBG_INFO(80, "%s: Setting Graphics Clock to %d\n", FN_NAME, speedInMHz);
|
|
|
|
HWC_IO_STORE( bInfo->regInfo, dramInit0, dramInit0);
|
|
HWC_IO_STORE( bInfo->regInfo, dramInit1, dramInit1);
|
|
HWC_IO_STORE( bInfo->regInfo, pllCtrl1, pllCtrl1);
|
|
|
|
return FXTRUE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcSetGrxClock */
|
|
|
|
FxBool
|
|
hwcSetMemClock(hwcBoardInfo *bInfo, FxU32 speedInMHz)
|
|
{
|
|
#define FN_NAME "hwcSetMemClock"
|
|
return FXFALSE;
|
|
#undef FN_NAME
|
|
} /* hwcSetMemClock */
|
|
|
|
char *
|
|
hwcGetenv(char *a)
|
|
{
|
|
envitem *ptr;
|
|
|
|
char *result;
|
|
result=getenv(a);
|
|
if (result) return result;
|
|
if (!envinit) loadEnvFile();
|
|
ptr=first;
|
|
while (ptr) {
|
|
if (!strcmp(ptr->env, a)) return ptr->val;
|
|
ptr=ptr->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
FxBool
|
|
hwcResolutionSupported(hwcBoardInfo *bInfo, GrScreenResolution_t res)
|
|
{
|
|
#define FN_NAME "hwcResolutionSupported"
|
|
|
|
/* For now we're just going to retur TRUE. We should check with
|
|
vmode extension to see if the requested size is available */
|
|
return FXTRUE;
|
|
|
|
#undef FN_NAME
|
|
} /* hwcResolutionSupported */
|
|
|
|
void grDRIImportFifo(int fifoPtr, int fifoRead)
|
|
{
|
|
_grImportFifo(fifoPtr, fifoRead);
|
|
}
|
|
|
|
void grDRIInvalidateAll() {
|
|
_grInvalidateAll();
|
|
}
|
|
|
|
void grDRIResetSAREA()
|
|
{
|
|
_grExportFifo((int *)driInfo.fifoPtr, (int *)driInfo.fifoRead);
|
|
}
|