1468 lines
50 KiB
C
1468 lines
50 KiB
C
/*-*-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
|
|
**
|
|
**
|
|
** $Revision$
|
|
** $Date$
|
|
**
|
|
** Initialization code for initializing SST-1 video unit
|
|
**
|
|
*/
|
|
#ifdef __WIN32__
|
|
#pragma optimize ("",off)
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#ifdef BUILD_FOR_SST1
|
|
#include <sst.h>
|
|
#else
|
|
#include <3dfx.h>
|
|
#include <cvgregs.h>
|
|
#include <cvgdefs.h>
|
|
#endif
|
|
#define FX_DLL_DEFINITION
|
|
#include <fxdll.h>
|
|
#define SST1INIT_VIDEO_ALLOCATE // allocate data structures for video timing
|
|
#include <sst1vid.h>
|
|
#include <sst1init.h>
|
|
|
|
#ifdef H3D
|
|
#include <h3dglide.h>
|
|
#endif
|
|
|
|
#include "canopus.h"
|
|
|
|
/*
|
|
** sst1InitVideo():
|
|
** Initialize video (including DAC setup) for the specified resolution
|
|
**
|
|
** Note: sst1InitVideo() is included for compatibility with SST-1 apps only
|
|
** and should not be used for Voodoo2. Use sst1InitVideoBuffers() instead.
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitVideo(FxU32 *sstbase,
|
|
GrScreenResolution_t screenResolution, GrScreenRefresh_t screenRefresh,
|
|
void *placeHolder)
|
|
{
|
|
FxU32 memSizeInPages;
|
|
sst1VideoTimingStruct *videoTiming;
|
|
FxU32 colorBuffs, auxBuffs;
|
|
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(GETENV(("SSTV2_IGNORE_INIT_VIDEO"))) {
|
|
INIT_PRINTF(("WARNING: Ignoring sst1InitVideo()...\n"));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
return(FXTRUE);
|
|
}
|
|
|
|
if(!(videoTiming = sst1InitFindVideoTimingStruct(screenResolution,
|
|
screenRefresh)))
|
|
return(FXFALSE);
|
|
|
|
if(sst1CurrentBoard->fbiMemSize == 1)
|
|
memSizeInPages = 256;
|
|
else if(sst1CurrentBoard->fbiMemSize == 2)
|
|
memSizeInPages = 512;
|
|
else
|
|
memSizeInPages = 1024;
|
|
if(sst1CurrentBoard->sliDetected)
|
|
memSizeInPages <<= 1;
|
|
|
|
// Do we have enough memory for the desired resolution?
|
|
if(memSizeInPages > (3 * videoTiming->memOffset)) {
|
|
colorBuffs = 2;
|
|
auxBuffs = 1;
|
|
} else if(memSizeInPages > (2 * videoTiming->memOffset)) {
|
|
colorBuffs = 2;
|
|
auxBuffs = 0;
|
|
} else {
|
|
INIT_PRINTF(("sst1InitVideo(): Insufficient memory available for desired resolution...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
|
|
return(sst1InitVideoBuffers(sstbase, screenResolution, screenRefresh,
|
|
colorBuffs, auxBuffs, (sst1VideoTimingStruct *) NULL, FXTRUE));
|
|
}
|
|
|
|
/*
|
|
** sst1InitVideoBuffers():
|
|
** Initialize video (including DAC setup) for the specified resolution
|
|
**
|
|
** Returns:
|
|
** FXTRUE if successfully initializes specified SST-1 video resolution
|
|
** FXFALSE if cannot initialize SST-1 to specified video resolution
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitVideoBuffers(FxU32 *sstbase,
|
|
GrScreenResolution_t screenResolution, GrScreenRefresh_t screenRefresh,
|
|
FxU32 nColorBuffs, FxU32 nAuxBuffs, sst1VideoTimingStruct *altVideoTiming,
|
|
FxBool switchPassThru)
|
|
{
|
|
FxU32 n, vtmp;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
sst1VideoTimingStruct *sstVideoRez;
|
|
FxU32 video16BPP;
|
|
FxU32 memFifoLwm, memFifoHwm, pciFifoLwm;
|
|
FxU32 vInClkDel, vOutClkDel;
|
|
FxU32 tf0_clkdel, tf1_clkdel, tf2_clkdel;
|
|
FxU32 ft_clkdel, memSizeInPages;
|
|
FxU32 nCol, nAux, miscCtrl;
|
|
int memFifoEntries;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(GETENV(("SSTV2_IGNORE_INIT_VIDEO"))) {
|
|
INIT_PRINTF(("WARNING: Ignoring sst1InitVideo()...\n"));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
return(FXTRUE);
|
|
}
|
|
|
|
if(altVideoTiming && !GETENV(("SSTV2_SCREENREZ")) &&
|
|
!GETENV(("SSTV2_SCREENREFRESH")))
|
|
sstVideoRez = altVideoTiming;
|
|
else {
|
|
if(!(sstVideoRez = sst1InitFindVideoTimingStruct(screenResolution,
|
|
screenRefresh)))
|
|
return(FXFALSE);
|
|
}
|
|
|
|
nCol = nColorBuffs;
|
|
nAux = nAuxBuffs;
|
|
|
|
// Disallow unsupported buffer combinations...
|
|
if(nCol < 2 || nCol > 3 || nAux > 1)
|
|
return(FXFALSE);
|
|
|
|
if(sst1CurrentBoard->fbiMemSize == 1)
|
|
memSizeInPages = 256;
|
|
else if(sst1CurrentBoard->fbiMemSize == 2)
|
|
memSizeInPages = 512;
|
|
else
|
|
memSizeInPages = 1024;
|
|
if(sst1CurrentBoard->sliDetected)
|
|
memSizeInPages <<= 1;
|
|
|
|
// To be compatible with Voodoo1, if there is enough memory to
|
|
// allocate an aux buffer, then do it...
|
|
if(nCol == 2 && nAux == 0) {
|
|
if(memSizeInPages > (3 * sstVideoRez->memOffset)) {
|
|
INIT_PRINTF(("sst1InitVideo(): Allocating 1 Aux Buffer for SST-1 Compatibility...\n"));
|
|
nAux++;
|
|
}
|
|
}
|
|
|
|
if(GETENV(("SSTV2_ALLOC_COLOR")))
|
|
nCol = ATOI(GETENV(("SSTV2_ALLOC_COLOR")));
|
|
if(GETENV(("SSTV2_ALLOC_AUX")))
|
|
nAux = ATOI(GETENV(("SSTV2_ALLOC_AUX")));
|
|
|
|
// Disallow unsupported buffer combinations (from environment vars)...
|
|
if(nCol < 2 || nCol > 3 || nAux > 1)
|
|
return(FXFALSE);
|
|
|
|
//
|
|
// Do we have enough memory for the desired resolution?
|
|
//
|
|
if(memSizeInPages < ((nCol + nAux) * sstVideoRez->memOffset)) {
|
|
INIT_PRINTF(("sst1InitVideo(): Insufficient memory available for desired resolution.\n"));
|
|
return(FXFALSE);
|
|
}
|
|
if(GETENV(("SSTV2_VIDEO_24BPP")))
|
|
sst1CurrentBoard->fbiVideo16BPP =
|
|
(ATOI(GETENV(("SSTV2_VIDEO_24BPP")))) ^ 0x1;
|
|
else {
|
|
sst1CurrentBoard->fbiVideo16BPP = 0;
|
|
|
|
if(sst1CurrentBoard->fbiVideo16BPP && (sstVideoRez->video16BPPIsOK ==
|
|
FXFALSE))
|
|
sst1CurrentBoard->fbiVideo16BPP = 0;
|
|
if(!sst1CurrentBoard->fbiVideo16BPP && (sstVideoRez->video24BPPIsOK ==
|
|
FXFALSE))
|
|
sst1CurrentBoard->fbiVideo16BPP = 1;
|
|
|
|
if(altVideoTiming == (sst1VideoTimingStruct *) NULL) {
|
|
// Determine when cannot output 24bpp video...
|
|
// Cannot run at high frequencies across SLI connector...
|
|
if(sst1CurrentBoard->sliDetected &&
|
|
sstVideoRez->clkFreq24bpp > 90.0F)
|
|
sst1CurrentBoard->fbiVideo16BPP = 1;
|
|
}
|
|
}
|
|
video16BPP = sst1CurrentBoard->fbiVideo16BPP;
|
|
|
|
// Reset Video Refresh Unit
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_VIDEO_RESET);
|
|
|
|
// Setup SST video timing registers
|
|
if(GETENV(("SSTV2_HSYNC"))) {
|
|
SSCANF(GETENV(("SSTV2_HSYNC")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using SST_HSYNC=0x%x\n", vtmp));
|
|
ISET(sst->hSync, vtmp);
|
|
} else
|
|
ISET(sst->hSync, ((sstVideoRez->hSyncOff << SST_VIDEO_HSYNC_OFF_SHIFT) |
|
|
(sstVideoRez->hSyncOn << SST_VIDEO_HSYNC_ON_SHIFT)));
|
|
if(GETENV(("SSTV2_VSYNC"))) {
|
|
SSCANF(GETENV(("SSTV2_VSYNC")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using SST_VSYNC=0x%x\n", vtmp));
|
|
ISET(sst->vSync, vtmp);
|
|
} else
|
|
ISET(sst->vSync, ((sstVideoRez->vSyncOff << SST_VIDEO_VSYNC_OFF_SHIFT) |
|
|
(sstVideoRez->vSyncOn << SST_VIDEO_VSYNC_ON_SHIFT)));
|
|
if(GETENV(("SSTV2_BACKPORCH"))) {
|
|
SSCANF(GETENV(("SSTV2_BACKPORCH")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using SST_BACKPORCH=0x%x\n", vtmp));
|
|
ISET(sst->backPorch, vtmp);
|
|
} else
|
|
ISET(sst->backPorch,
|
|
((sstVideoRez->vBackPorch << SST_VIDEO_VBACKPORCH_SHIFT) |
|
|
(sstVideoRez->hBackPorch << SST_VIDEO_HBACKPORCH_SHIFT)));
|
|
if(GETENV(("SSTV2_DIMENSIONS"))) {
|
|
SSCANF(GETENV(("SSTV2_DIMENSIONS")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using SST_DIMENSIONS=0x%x\n", vtmp));
|
|
sstVideoRez->yDimension = (vtmp >> SST_VIDEO_YDIM_SHIFT) & 0x3ff;
|
|
sstVideoRez->xDimension = vtmp & 0x3ff;
|
|
}
|
|
ISET(sst->videoDimensions,
|
|
((sstVideoRez->yDimension << SST_VIDEO_YDIM_SHIFT) |
|
|
((sstVideoRez->xDimension-1) << SST_VIDEO_XDIM_SHIFT)));
|
|
if(GETENV(("SSTV2_MEMOFFSET"))) {
|
|
SSCANF(GETENV(("SSTV2_MEMOFFSET")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using video memOffset=0x%x\n", vtmp));
|
|
sstVideoRez->memOffset = vtmp;
|
|
}
|
|
if(GETENV(("SSTV2_TILESINX"))) {
|
|
SSCANF(GETENV(("SSTV2_TILESINX")), "%ld", &vtmp);
|
|
INIT_PRINTF(("sst1InitVideo(): Using video tilesInX=0x%x\n", vtmp));
|
|
sstVideoRez->tilesInX = vtmp;
|
|
}
|
|
|
|
// Update info structure
|
|
sst1CurrentBoard->fbiVideoWidth = sstVideoRez->xDimension;
|
|
sst1CurrentBoard->fbiVideoHeight = sstVideoRez->yDimension;
|
|
sst1CurrentBoard->fbiVideoRefresh = sstVideoRez->refreshRate;
|
|
sst1CurrentBoard->fbiVideoColBuffs = nCol;
|
|
sst1CurrentBoard->fbiVideoAuxBuffs = nAux;
|
|
sst1CurrentBoard->fbiVideoMemOffset = sstVideoRez->memOffset;
|
|
sst1CurrentBoard->fbiVideoTilesInX = sstVideoRez->tilesInX;
|
|
sst1CurrentBoard->fbiVideoStruct = sstVideoRez;
|
|
|
|
// Setup SST memory mapper for desired resolution
|
|
if(sst1CurrentBoard->fbiMemSize == 4)
|
|
sst1InitSetResolution(sstbase, sstVideoRez, 1);
|
|
else
|
|
sst1InitSetResolution(sstbase, sstVideoRez, 0);
|
|
|
|
// Calculate graphics clock frequency
|
|
if(sst1InitCalcGrxClk(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Setup video fifo
|
|
// NOTE: Lower values for the video fifo threshold improve video fifo
|
|
// underflow problems
|
|
if(GETENV(("SSTV2_VFIFO_THRESH"))) {
|
|
INIT_PRINTF(("sst1InitVideo(): Overriding Default Video Fifo Threshold %d and Storing %d\n",
|
|
sstVideoRez->vFifoThreshold, ATOI(GETENV(("SSTV2_VFIFO_THRESH")))));
|
|
ISET(sst->fbiInit3, (IGET(sst->fbiInit3) & ~SST_VIDEO_FIFO_THRESH) |
|
|
|
|
((ATOI(GETENV(("SSTV2_VFIFO_THRESH"))))
|
|
<< SST_VIDEO_FIFO_THRESH_SHIFT));
|
|
} else {
|
|
FxU32 vFifoThresholdVal = sstVideoRez->vFifoThreshold;
|
|
|
|
if(sst1CurrentBoard->fbiGrxClkFreq < 45)
|
|
// Lower threshold value for slower graphics clocks
|
|
vFifoThresholdVal = sstVideoRez->vFifoThreshold - 4;
|
|
|
|
ISET(sst->fbiInit3, (IGET(sst->fbiInit3) & ~SST_VIDEO_FIFO_THRESH) |
|
|
(vFifoThresholdVal << SST_VIDEO_FIFO_THRESH_SHIFT));
|
|
}
|
|
|
|
INIT_PRINTF(("sst1InitVideo() Setting up video for resolution (%d, %d), Refresh:%d Hz...\n",
|
|
sstVideoRez->xDimension, sstVideoRez->yDimension,
|
|
sstVideoRez->refreshRate));
|
|
INIT_PRINTF(("sst1InitVideo(): Video Fifo Threshold = %d\n",
|
|
(IGET(sst->fbiInit3) & SST_VIDEO_FIFO_THRESH) >>
|
|
SST_VIDEO_FIFO_THRESH_SHIFT));
|
|
|
|
// Initialize Y-Origin
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
ISET(sst->fbiInit3, (IGET(sst->fbiInit3) & ~SST_YORIGIN_TOP) |
|
|
((sstVideoRez->yDimension - 1) << SST_YORIGIN_TOP_SHIFT));
|
|
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
memFifoLwm = 23;
|
|
if(GETENV(("SSTV2_MEMFIFO_LWM")))
|
|
SSCANF(GETENV(("SSTV2_MEMFIFO_LWM")), "%ld", &memFifoLwm);
|
|
memFifoHwm = 54;
|
|
if(GETENV(("SSTV2_MEMFIFO_HWM")))
|
|
SSCANF(GETENV(("SSTV2_MEMFIFO_HWM")), "%ld", &memFifoHwm);
|
|
pciFifoLwm = 13;
|
|
if(GETENV(("SSTV2_PCIFIFO_LWM")))
|
|
SSCANF(GETENV(("SSTV2_PCIFIFO_LWM")), "%ld", &pciFifoLwm);
|
|
INIT_PRINTF(("sst1InitVideo(): pciFifoLwm:%d memFifoLwm:%d memFifoHwm:%d\n",
|
|
pciFifoLwm, memFifoLwm, memFifoHwm));
|
|
|
|
// Setup Memory FIFO
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) &
|
|
~(SST_MEM_FIFO_ROW_BASE | SST_MEM_FIFO_ROW_ROLL | SST_MEM_FIFO_LWM));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
if(sst1CurrentBoard->fbiMemSize == 1)
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) |
|
|
(0xff << SST_MEM_FIFO_ROW_ROLL_SHIFT));
|
|
else if (sst1CurrentBoard->fbiMemSize == 2)
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) |
|
|
(0x1ff << SST_MEM_FIFO_ROW_ROLL_SHIFT));
|
|
else
|
|
// 4 MBytes frame buffer memory...
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) |
|
|
(0x3ff << SST_MEM_FIFO_ROW_ROLL_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
// Setup buffer management...
|
|
if(sst1InitAllocBuffers(sstbase, nCol, nAux) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
INIT_PRINTF(("sst1InitVideo(): Allocating %d Color Buffers and %d Aux Buffer(s)...\n",
|
|
sst1CurrentBoard->fbiVideoColBuffs, sst1CurrentBoard->fbiVideoAuxBuffs));
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) |
|
|
(((nCol+nAux)*sstVideoRez->memOffset) << SST_MEM_FIFO_ROW_BASE_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
ISET(sst->fbiInit4, IGET(sst->fbiInit4) |
|
|
(memFifoLwm << SST_MEM_FIFO_LWM_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
// Set PCI FIFO LWM
|
|
ISET(sst->fbiInit0, (IGET(sst->fbiInit0) & ~SST_PCI_FIFO_LWM) |
|
|
(pciFifoLwm << SST_PCI_FIFO_LWM_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
// Enable Memory Fifo...
|
|
if(GETENV(("SSTV2_MEMFIFO")))
|
|
n = ATOI(GETENV(("SSTV2_MEMFIFO")));
|
|
else
|
|
n = 1;
|
|
|
|
if(n) {
|
|
sst1CurrentBoard->fbiMemoryFifoEn = 1;
|
|
memFifoEntries = (65536 - (int)
|
|
(((int) (memSizeInPages - 1) -
|
|
(int) ((nCol+nAux) * sstVideoRez->memOffset)) * 512)) >> 5;
|
|
if(memFifoEntries <= 256)
|
|
memFifoEntries = 0x100; // max. memory fifo size...
|
|
else if(memFifoEntries >= 2048) {
|
|
INIT_PRINTF(("sst1InitVideo(): Invalid memFifoEntries 0x%x\n",
|
|
memFifoEntries));
|
|
return(FXFALSE);
|
|
}
|
|
if(GETENV(("SSTV2_MEMFIFO_ENTRIES")))
|
|
SSCANF(GETENV(("SSTV2_MEMFIFO_ENTRIES")), "%d", &memFifoEntries);
|
|
INIT_PRINTF(("sst1InitVideo(): Enabling Memory FIFO (Entries=%d)...\n",
|
|
65536 - (memFifoEntries << 5)));
|
|
|
|
sst1CurrentBoard->memFifoStatusLwm = (memFifoEntries << 5) | 0x1f;
|
|
ISET(sst->fbiInit0, (IGET(sst->fbiInit0) & ~(SST_MEM_FIFO_EN |
|
|
SST_MEM_FIFO_HWM | SST_PCI_FIFO_LWM | SST_MEM_FIFO_BURST_HWM)) |
|
|
(memFifoEntries << SST_MEM_FIFO_HWM_SHIFT) |
|
|
(pciFifoLwm << SST_PCI_FIFO_LWM_SHIFT) |
|
|
(memFifoHwm << SST_MEM_FIFO_BURST_HWM_SHIFT) |
|
|
SST_MEM_FIFO_EN);
|
|
INIT_PRINTF(("sst1InitVideo(): Setting memory FIFO LWM to 0x%x (%d)\n",
|
|
sst1CurrentBoard->memFifoStatusLwm,
|
|
sst1CurrentBoard->memFifoStatusLwm));
|
|
}
|
|
|
|
vInClkDel = 1;
|
|
if(GETENV(("SSTV2_VIN_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_VIN_CLKDEL")), "%ld", &vInClkDel);
|
|
|
|
vOutClkDel = 0;
|
|
if(GETENV(("SSTV2_VOUT_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_VOUT_CLKDEL")), "%ld", &vOutClkDel);
|
|
|
|
INIT_PRINTF(("sst1InitVideo(): vInClkDel=0x%x vOutClkDel=0x%x\n",
|
|
|
|
vInClkDel, vOutClkDel));
|
|
|
|
// Setup miscellaneous control
|
|
miscCtrl = 0;
|
|
if(sstVideoRez->miscCtrl & BIT(0))
|
|
miscCtrl |= SST_SCAN_DOUBLE_HORIZ;
|
|
if(sstVideoRez->miscCtrl & BIT(1))
|
|
miscCtrl |= SST_SCAN_DOUBLE_VERT;
|
|
if(sstVideoRez->miscCtrl & BIT(2))
|
|
miscCtrl |= SST_INVERT_HSYNC;
|
|
if(sstVideoRez->miscCtrl & BIT(3))
|
|
miscCtrl |= SST_INVERT_VSYNC;
|
|
|
|
// Drive dac output signals and select input video clock
|
|
if(video16BPP) {
|
|
INIT_PRINTF(("sst1InitVideo(): Setting 16BPP video mode...\n"));
|
|
ISET(sst->fbiInit1, (IGET(sst->fbiInit1) & ~SST_VIDEO_MASK) |
|
|
(SST_VIDEO_DATA_OE_EN |
|
|
SST_VIDEO_BLANK_OE_EN |
|
|
SST_VIDEO_HVSYNC_OE_EN |
|
|
SST_VIDEO_DCLK_OE_EN |
|
|
SST_VIDEO_VID_CLK_2X |
|
|
(vInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
|
|
(vOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
|
|
SST_VIDEO_VCLK_SEL));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
ISET(sst->fbiInit5, IGET(sst->fbiInit5) | miscCtrl);
|
|
} else {
|
|
INIT_PRINTF(("sst1InitVideo(): Setting 24BPP video mode...\n"));
|
|
#if 0
|
|
// Old clock settings -- probably use for true 24-bit dac output
|
|
ISET(sst->fbiInit1, (IGET(sst->fbiInit1) & ~SST_VIDEO_MASK) |
|
|
(SST_VIDEO_DATA_OE_EN |
|
|
SST_VIDEO_BLANK_OE_EN |
|
|
SST_VIDEO_HVSYNC_OE_EN |
|
|
SST_VIDEO_DCLK_OE_EN |
|
|
SST_VIDEO_VID_CLK_2X |
|
|
SST_VIDEO_VCLK_DIV2 |
|
|
(vInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
|
|
(vOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
|
|
SST_VIDEO_24BPP_EN));
|
|
#else
|
|
ISET(sst->fbiInit1, (IGET(sst->fbiInit1) & ~SST_VIDEO_MASK) |
|
|
(SST_VIDEO_DATA_OE_EN |
|
|
SST_VIDEO_BLANK_OE_EN |
|
|
SST_VIDEO_HVSYNC_OE_EN |
|
|
SST_VIDEO_DCLK_OE_EN |
|
|
// SST_VIDEO_VID_CLK_2X | // BIT(17)
|
|
// SST_VIDEO_VCLK_DIV2 | // MUX select 0x1
|
|
(0x0 << SST_VIDEO_VCLK_SEL_SHIFT) | // MUX select 0x0
|
|
(vInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
|
|
(vOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
|
|
SST_VIDEO_24BPP_EN));
|
|
ISET(sst->fbiInit5, IGET(sst->fbiInit5) |
|
|
SST_VIDEO_CLK_SLAVE_OE_EN | SST_VID_CLK_2X_OUT_OE_EN |
|
|
SST_VID_CLK_DAC_DATA16_SEL | miscCtrl);
|
|
#endif
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
if(!GETENV(("SSTV2_VIDEO_FILTER_DISABLE"))) {
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_VIDEO_FILTER_EN);
|
|
if(GETENV(("SSTV2_VIDEO_FILTER_THRESHOLD"))) {
|
|
SSCANF(GETENV(("SSTV2_VIDEO_FILTER_THRESHOLD")), "%ld", &n);
|
|
INIT_PRINTF(("sst1InitVideo(): Setting Video Filtering Treshold to 0x%x...\n", n));
|
|
|
|
ISET(sst->videoFilterRgbThreshold, n);
|
|
} else
|
|
// ISET(sst->videoFilterRgbThreshold, 0x180c18);
|
|
ISET(sst->videoFilterRgbThreshold, 0x080408);
|
|
} else
|
|
INIT_PRINTF(("sst1InitVideo(): Disabling Video Filtering...\n"));
|
|
}
|
|
|
|
// Setup prelim. clock delay values...
|
|
if(sst1CurrentBoard->fbiBoardID == 0x3) {
|
|
// Early 4-layer 4220 board -- Runs at 83 MHz by default...
|
|
if(sst1CurrentBoard->fbiGrxClkFreq <= 80) {
|
|
ft_clkdel = 0x5;
|
|
tf0_clkdel = 0x7;
|
|
tf1_clkdel = 0x8;
|
|
tf2_clkdel = 0x8;
|
|
} else {
|
|
ft_clkdel = 0x4;
|
|
tf0_clkdel = 0x6;
|
|
tf1_clkdel = 0x7;
|
|
tf2_clkdel = 0x7;
|
|
}
|
|
} else if(sst1CurrentBoard->fbiBoardID == 0x2) {
|
|
// 4400 8-layer bringup board -- Runs at 90 MHz by default...
|
|
ft_clkdel = 0x4;
|
|
tf0_clkdel = 0x6;
|
|
tf1_clkdel = 0x6;
|
|
tf2_clkdel = 0x6;
|
|
} else {
|
|
// Setup basic values...
|
|
ft_clkdel = 0x4;
|
|
tf0_clkdel = 0x6;
|
|
tf1_clkdel = 0x6;
|
|
tf2_clkdel = 0x6;
|
|
}
|
|
|
|
ISET(sst->fbiInit3, (IGET(sst->fbiInit3) & ~SST_FT_CLK_DEL_ADJ) |
|
|
(ft_clkdel << SST_FT_CLK_DEL_ADJ_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
sst1CurrentBoard->tmuInit1[0] = (sst1CurrentBoard->tmuInit1[0] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf0_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
sst1CurrentBoard->tmuInit1[1] = (sst1CurrentBoard->tmuInit1[1] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf1_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
sst1CurrentBoard->tmuInit1[2] = (sst1CurrentBoard->tmuInit1[2] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf2_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
|
|
// Calling sst1InitResetTmus() will put the new trexinit values in the
|
|
// TMUs, as well as reset FBI and TMU...
|
|
sst1InitResetTmus(sstbase);
|
|
|
|
/* If we're running on a canopus board we now have to calculate
|
|
* the actual final clock delays and set them otherwise the video
|
|
* reset is going to wait forever because the hw is never going to
|
|
* become idle waiting for pixels from the tmu's.
|
|
*/
|
|
if (sst1CurrentBoard->fbiBoardID == CANOPUS_ID) {
|
|
// Setup graphics clock to 90 MHz for clockdelay measurement
|
|
if (!sst1SetGrxClk_Canopus(sstbase, 90))
|
|
return(FXFALSE);
|
|
|
|
// Calculate final clock delay values...
|
|
if(!sst1InitSetClkDelays(sstbase)) {
|
|
INIT_PRINTF(("sst1InitVideo() ERROR: Could not calculate clock delay values...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
}
|
|
|
|
|
|
// Setup graphics clock
|
|
if(sst1InitGrxClk(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Setup video mode
|
|
if(sst1InitSetVidMode(sstbase, video16BPP) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Adjust Video Clock
|
|
#ifndef DIRECTX
|
|
if(GETENV(("SSTV2_VIDCLK2X"))) {
|
|
float vidClkFreq;
|
|
|
|
SSCANF(GETENV(("SSTV2_VIDCLK2X")), "%f", &vidClkFreq);
|
|
if(sst1InitSetVidClk(sstbase, vidClkFreq) == FXFALSE)
|
|
return(FXFALSE);
|
|
} else {
|
|
#endif
|
|
if(sst1InitUseVoodooFile == FXTRUE) {
|
|
if(sst1InitSetVidClkINI(sstbase, sst1CurrentBoard->fbiVideoWidth,
|
|
sst1CurrentBoard->fbiVideoHeight,
|
|
sst1CurrentBoard->fbiVideoRefresh, video16BPP) == FXFALSE)
|
|
return(FXFALSE);
|
|
} else {
|
|
if(video16BPP) {
|
|
if(sst1InitSetVidClk(sstbase, sstVideoRez->clkFreq16bpp) ==
|
|
FXFALSE)
|
|
return(FXFALSE);
|
|
} else {
|
|
if(sst1InitSetVidClk(sstbase, sstVideoRez->clkFreq24bpp) ==
|
|
FXFALSE)
|
|
return(FXFALSE);
|
|
}
|
|
}
|
|
#ifndef DIRECTX
|
|
}
|
|
#endif
|
|
|
|
// Wait for video clock to stabilize
|
|
for(n=0; n<200000; n++)
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
// Run Video Reset Module
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) & ~SST_VIDEO_RESET);
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
ISET(sst->fbiInit2, IGET(sst->fbiInit2) | SST_EN_DRAM_REFRESH);
|
|
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
// Calculate final clock delay values...
|
|
if(sst1InitSetClkDelays(sstbase) == FXFALSE) {
|
|
INIT_PRINTF(("sst1InitVideo() ERROR: Could not calculate clock delay values...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
|
|
// Clear memory...
|
|
if(!GETENV(("SSTV2_VIDEO_NOCLEAR"))) {
|
|
FxU32 clearColor = 0x0;
|
|
FxU32 pagesToFill;
|
|
|
|
if(GETENV(("SSTV2_VIDEO_CLEARCOLOR")))
|
|
SSCANF(GETENV(("SSTV2_VIDEO_CLEARCOLOR")), "%ld", &clearColor);
|
|
|
|
if(sst1CurrentBoard->fbiMemSize == 1)
|
|
pagesToFill = 256;
|
|
else if(sst1CurrentBoard->fbiMemSize == 2)
|
|
pagesToFill = 512;
|
|
else
|
|
pagesToFill = 1024;
|
|
|
|
ISET(sst->bltColor, clearColor);
|
|
ISET(sst->bltDstXY, 0x0);
|
|
ISET(sst->bltSize, ((pagesToFill-1)<<16) | 511);
|
|
ISET(sst->bltCommand, SSTG_FRECTFILL | SSTG_GO);
|
|
sst1InitIdle(sstbase);
|
|
} else
|
|
INIT_PRINTF(("sst1InitVideo(): Not Clearing Frame Buffer...\n"));
|
|
|
|
// Clear fbistat registers after clearing screen
|
|
ISET(sst->nopCMD, 0x3);
|
|
|
|
// Only switch passthrough and do monitor detection if
|
|
// requested.
|
|
if(switchPassThru == FXTRUE)
|
|
{
|
|
// 3D now owns monitor...
|
|
sst1InitVgaPassCtrl(sstbase, 0);
|
|
|
|
// Detect presence of monitor...
|
|
sst1InitMonitorDetect(sstbase);
|
|
INIT_PRINTF(("sst1InitVideo(): Monitor Detected:%d\n",
|
|
sst1CurrentBoard->monitorDetected));
|
|
|
|
// sst1InitMonitorDetect() trashes the gamma table. Reload to the
|
|
// original value if sst1InitGamma() has already been called -- otherwise
|
|
// load a 1.0 gamma table
|
|
if(sst1CurrentBoard->fbiInitGammaDone)
|
|
sst1InitGammaRGB(sstbase, sst1CurrentBoard->fbiGammaRed,
|
|
sst1CurrentBoard->fbiGammaGreen, sst1CurrentBoard->fbiGammaBlue);
|
|
else {
|
|
// Do not display gamma values when called by sst1InitVideo()...
|
|
sst1CurrentBoard->fbiInitGammaDone = 1;
|
|
sst1InitGammaRGB(sstbase, (double) 1.0, (double) 1.0, (double) 1.0);
|
|
sst1CurrentBoard->fbiInitGammaDone = 0;
|
|
}
|
|
}
|
|
|
|
if(GETENV(("SSTV2_VIDEO_DISABLE"))) {
|
|
INIT_PRINTF(("sst1InitVideo(): Disabling video timing...\n"));
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_VIDEO_RESET);
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
}
|
|
sst1InitIdle(sstbase);
|
|
|
|
if(((IGET(sst->status) & SST_SWAPBUFPENDING) >>
|
|
SST_SWAPBUFPENDING_SHIFT) > 0)
|
|
sst1InitClearSwapPending(sstbase);
|
|
|
|
// Since initVideo() is the last init call, if the user wants to
|
|
// disable idling, do it here. This way, all the calls to initIdle
|
|
// required within the init code still idle the hardware.
|
|
if(GETENV(("SSTV2_IGNORE_IDLE"))) {
|
|
INIT_PRINTF(("sst1InitVideo(): Ignoring calls to sst1InitIdle()...\n"));
|
|
initIdleEnabled = 0;
|
|
}
|
|
|
|
// Update info structure for initEnable
|
|
PCICFG_RD(SST1_PCI_INIT_ENABLE, sst1CurrentBoard->fbiInitEnable);
|
|
|
|
// If this board is SLI-capable, tristate the video output signals so
|
|
// that monitor detection will work properly for the second board. The
|
|
// video output signals will be re-enabled during SLI initialization for
|
|
// the Master board
|
|
if(sst1CurrentBoard->sliDetected) {
|
|
INIT_PRINTF(("sst1InitVideo(): Disabling video output signals for proper monitor detection...\n"));
|
|
sst1InitVideoShutdown(sstbase, FXFALSE);
|
|
}
|
|
|
|
INIT_PRINTF(("sst1InitVideo() exiting with status %d...\n", FXTRUE));
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitAllocBuffers():
|
|
** Initialize video for buffer management
|
|
**
|
|
*/
|
|
static FxBool
|
|
sst1InitAllocBuffersDirect(FxU32 *sstbase, FxU32 nColorBuffs, FxU32 nAuxBuffs)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 nCol = nColorBuffs;
|
|
FxU32 nAux = nAuxBuffs;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
// Setup buffer management...
|
|
if(nCol == 2 && nAux == 0)
|
|
ISET(sst->fbiInit5, (IGET(sst->fbiInit5) & ~SST_BUFFER_ALLOC) |
|
|
SST_BUFFER_ALLOC_2C0Z);
|
|
else if(nCol == 2 && nAux == 1)
|
|
ISET(sst->fbiInit5, (IGET(sst->fbiInit5) & ~SST_BUFFER_ALLOC) |
|
|
SST_BUFFER_ALLOC_2C1Z);
|
|
else if(nCol == 3 && nAux == 0)
|
|
ISET(sst->fbiInit5, (IGET(sst->fbiInit5) & ~SST_BUFFER_ALLOC) |
|
|
SST_BUFFER_ALLOC_3C0Z);
|
|
else if(nCol == 3 && nAux == 1)
|
|
ISET(sst->fbiInit5, (IGET(sst->fbiInit5) & ~SST_BUFFER_ALLOC) |
|
|
SST_BUFFER_ALLOC_3C1Z);
|
|
else {
|
|
INIT_PRINTF(("sst1InitAllocBuffers(): Unsupported Color/Aux buffer combination (%d/%d)\n",
|
|
nCol, nAux));
|
|
return(FXFALSE);
|
|
}
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
FX_EXPORT FxBool FX_CSTYLE
|
|
sst1InitAllocBuffers(FxU32 *sstbase, FxU32 nColorBuffs, FxU32 nAuxBuffs)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxBool retVal;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
retVal = sst1InitAllocBuffersDirect(sstbase,
|
|
nColorBuffs, nAuxBuffs);
|
|
|
|
if (retVal && sst1CurrentBoard->sliDetected) {
|
|
/* NB: When writing to the slave we need to make sure that it does
|
|
* not have a client callback installed.
|
|
*/
|
|
FxSet32Proc saveProc = sst1CurrentBoard->set32;
|
|
sst1CurrentBoard->set32 = NULL;
|
|
|
|
sst1InitAllocBuffersDirect(sst1CurrentBoard->sliSlaveVirtAddr,
|
|
nColorBuffs, nAuxBuffs);
|
|
|
|
sst1CurrentBoard->set32 = saveProc;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/*
|
|
** sst1InitVideoShutdown():
|
|
** Shutdown video by not driving video outputs
|
|
** Do not reset the video engine
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitVideoShutdown(FxU32 *sstbase,
|
|
FxBool switchPassThruToVGA)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
ISET(sst->fbiInit1, (IGET(sst->fbiInit1) & ~(SST_VIDEO_DATA_OE_EN |
|
|
SST_VIDEO_DCLK_OE_EN | SST_VIDEO_HVSYNC_OE_EN)) | SST_VIDEO_BLANK_EN);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->fbiInit5, IGET(sst->fbiInit5) & ~(
|
|
SST_VIDEO_CLK_SLAVE_OE_EN | SST_VID_CLK_2X_OUT_OE_EN));
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
if(switchPassThruToVGA == FXTRUE)
|
|
// 2D/VGA now owns monitor...
|
|
sst1InitVgaPassCtrl(sstbase, 1);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitSetVidMode():
|
|
** Set video Mode
|
|
**
|
|
*/
|
|
FxBool sst1InitSetVidMode(FxU32 *sstbase, FxU32 video16BPP)
|
|
{
|
|
int helper = (GETENV(("SSTV2_DEBUGDAC"))) ? 1 : 0;
|
|
|
|
if(helper)
|
|
INIT_PRINTF(("sst1InitSetVidMode(): Entered...\n"));
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitUseVoodooFile == FXTRUE) {
|
|
return(sst1InitSetVidModeINI(sstbase, video16BPP));
|
|
} else {
|
|
if((sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ATT) ||
|
|
(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_TI))
|
|
return(sst1InitSetVidModeATT(sstbase, video16BPP));
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ICS)
|
|
return(sst1InitSetVidModeICS(sstbase, video16BPP));
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_PROXY)
|
|
return(FXTRUE); /* single board SLI - jeske */
|
|
else
|
|
return(FXFALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** sst1InitSetResolution():
|
|
** Setup FBI video resolution registers
|
|
** This routine is used by sst1InitVideo()
|
|
**
|
|
**
|
|
*/
|
|
FX_EXPORT void FX_CSTYLE sst1InitSetResolution(FxU32 *sstbase,
|
|
sst1VideoTimingStruct *sstVideoRez,
|
|
FxU32 Banked)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(Banked)
|
|
ISET(sst->fbiInit2, (IGET(sst->fbiInit2) & ~SST_VIDEO_BUFFER_OFFSET) |
|
|
(sstVideoRez->memOffset << SST_VIDEO_BUFFER_OFFSET_SHIFT) |
|
|
SST_DRAM_BANKING_CONFIG | SST_EN_DRAM_BANKED);
|
|
else
|
|
ISET(sst->fbiInit2, (IGET(sst->fbiInit2) & ~SST_VIDEO_BUFFER_OFFSET) |
|
|
(sstVideoRez->memOffset << SST_VIDEO_BUFFER_OFFSET_SHIFT));
|
|
|
|
ISET(sst->fbiInit1, (IGET(sst->fbiInit1) & ~SST_VIDEO_TILES_MASK) |
|
|
(((sstVideoRez->tilesInX>>1) & 0xF)<<SST_VIDEO_TILES_IN_X_SHIFT) |
|
|
(((sstVideoRez->tilesInX>>5) & 0x1)<<SST_VIDEO_TILES_IN_X_MSB_SHIFT));
|
|
|
|
// sst1CurrentBoard must be set previously with a sst1InitCheckBoard()
|
|
// call...
|
|
sst1CurrentBoard->fbiInit6 =
|
|
(sst1CurrentBoard->fbiInit6 & ~SST_VIDEO_TILES_IN_X_LSB) |
|
|
((sstVideoRez->tilesInX & 0x1)<<SST_VIDEO_TILES_IN_X_LSB_SHIFT);
|
|
ISET(sst->fbiInit6, sst1CurrentBoard->fbiInit6);
|
|
}
|
|
|
|
/*
|
|
** sst1InitSetVidClk():
|
|
** Set video clock
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitSetVidClk(FxU32 *sstbase, float vidClkFreq)
|
|
{
|
|
sst1ClkTimingStruct vidClkTiming;
|
|
int helper = (GETENV(("SSTV2_DEBUGDAC"))) ? 1 : 0;
|
|
|
|
if(helper)
|
|
|
|
INIT_PRINTF(("sst1InitSetVidClk(): Entered...\n"));
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitComputeClkParams(vidClkFreq, &vidClkTiming) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
INIT_PRINTF(("sst1InitSetVidClk(): Setting up %.2f MHz Video Clock...\n",
|
|
vidClkFreq));
|
|
|
|
if((sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ATT) ||
|
|
(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_TI))
|
|
return(sst1InitSetVidClkATT(sstbase, &vidClkTiming));
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ICS)
|
|
return(sst1InitSetVidClkICS(sstbase, &vidClkTiming));
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_PROXY)
|
|
return(FXTRUE); /* single board sli - jeske */
|
|
else
|
|
return(FXFALSE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitSetGrxClk():
|
|
** Set graphics clock
|
|
** NOTE: sst1InitSetGrxClk() resets the PCI fifo and the graphics subsystem
|
|
** of FBI
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitSetGrxClk(FxU32 *sstbase,
|
|
sst1ClkTimingStruct *sstGrxClk)
|
|
{
|
|
FxBool retVal = FXFALSE;
|
|
int helper = (GETENV(("SSTV2_DEBUGDAC"))) ? 1 : 0;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(helper)
|
|
INIT_PRINTF(("sst1InitSetGrxClk(): Entered...\n"));
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitUseVoodooFile == FXTRUE) {
|
|
retVal = sst1InitSetGrxClkINI(sstbase, sstGrxClk);
|
|
} else {
|
|
if((sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ATT) ||
|
|
(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_TI))
|
|
retVal = sst1InitSetGrxClkATT(sstbase, sstGrxClk);
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_ICS)
|
|
retVal = sst1InitSetGrxClkICS(sstbase, sstGrxClk);
|
|
else if(sst1CurrentBoard->fbiVideoDacType == SST_FBI_DACTYPE_PROXY) {
|
|
/* single board SLI - jeske*/
|
|
FxU32 i;
|
|
|
|
/* Reset graphics unit before we change grx clk */
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) |
|
|
(SST_GRX_RESET | SST_PCI_FIFO_RESET));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
|
|
for (i=0;i<boardsInSystem;i++) {
|
|
if ((i > 0) && (&sst1BoardInfo[i] == sst1CurrentBoard)) {
|
|
retVal = sst1InitSetGrxClk((FxU32 *)sst1BoardInfo[i-1].virtAddr[0],
|
|
sstGrxClk);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Wait for graphics clock to stabilize */
|
|
{ int n;
|
|
for(n=0; n<200000; n++)
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
/* Unreset PCI FIFO and graphic subsystem */
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_PCI_FIFO_RESET);
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_GRX_RESET);
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
}
|
|
|
|
}
|
|
}
|
|
if(retVal == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Always reset TMUs after a clock change...
|
|
return(sst1InitResetTmus(sstbase));
|
|
}
|
|
|
|
/*
|
|
** sst1InitVideoBorder():
|
|
** Initialize video color border
|
|
**
|
|
** The 'mask' parameter specifies which border(s) to enable:
|
|
** SST_COLOR_BORDER_LEFT_EN: Left edge
|
|
** SST_COLOR_BORDER_RIGHT_EN: Right edge
|
|
** SST_COLOR_BORDER_TOP_EN: Top edge
|
|
** SST_COLOR_BORDER_BOTTOM_EN: Bottom edge
|
|
** The 'color' parameter is in XXRRGGBB format
|
|
**
|
|
** Returns:
|
|
** FXTRUE if successfully initializes video color border
|
|
** FXFALSE if cannot initialize video color border
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitVideoBorder(FxU32 *sstbase,
|
|
FxU32 mask,
|
|
FxU32 color)
|
|
{
|
|
|
|
FxU32 fbiInit5;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
INIT_PRINTF(("sst1InitVideoBorder(): Setting border color to 0x%x...\n",
|
|
color));
|
|
|
|
fbiInit5 = IGET(sst->fbiInit5) &
|
|
~(SST_COLOR_BORDER_LEFT_EN | SST_COLOR_BORDER_RIGHT_EN |
|
|
SST_COLOR_BORDER_TOP_EN | SST_COLOR_BORDER_BOTTOM_EN);
|
|
fbiInit5 |=
|
|
(mask & SST_COLOR_BORDER_LEFT_EN) ? SST_COLOR_BORDER_LEFT_EN : 0;
|
|
fbiInit5 |=
|
|
(mask & SST_COLOR_BORDER_RIGHT_EN) ? SST_COLOR_BORDER_RIGHT_EN : 0;
|
|
fbiInit5 |=
|
|
(mask & SST_COLOR_BORDER_TOP_EN) ? SST_COLOR_BORDER_TOP_EN : 0;
|
|
fbiInit5 |=
|
|
(mask & SST_COLOR_BORDER_BOTTOM_EN) ? SST_COLOR_BORDER_BOTTOM_EN : 0;
|
|
|
|
ISET(sst->borderColor, color);
|
|
ISET(sst->fbiInit5, fbiInit5);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitFindVideoTimingStruct():
|
|
** Find SST-1 video timing data structure from GrScreenResolution_t and
|
|
** GrScreenRefresh_t input params
|
|
**
|
|
*/
|
|
|
|
FX_EXPORT sst1VideoTimingStruct* FX_CSTYLE
|
|
sst1InitFindVideoTimingStruct(GrScreenResolution_t screenResolution,
|
|
GrScreenRefresh_t screenRefresh)
|
|
{
|
|
GrScreenResolution_t screenRez = screenResolution;
|
|
GrScreenRefresh_t refreshRate = screenRefresh;
|
|
|
|
// Override Screen resolution with environment variables
|
|
if(GETENV(("SSTV2_SCREENREZ"))) {
|
|
FxU32 screenRezEnv = ATOI(GETENV(("SSTV2_SCREENREZ")));
|
|
|
|
switch(screenRezEnv) {
|
|
case 512256:
|
|
screenRez = GR_RESOLUTION_512x256;
|
|
break;
|
|
case 512:
|
|
screenRez = GR_RESOLUTION_512x384;
|
|
break;
|
|
case 640400:
|
|
screenRez = GR_RESOLUTION_640x400;
|
|
break;
|
|
case 800:
|
|
screenRez = GR_RESOLUTION_800x600;
|
|
break;
|
|
case 856:
|
|
screenRez = GR_RESOLUTION_856x480;
|
|
break;
|
|
case 960:
|
|
screenRez = GR_RESOLUTION_960x720;
|
|
break;
|
|
case 1024:
|
|
screenRez = GR_RESOLUTION_1024x768;
|
|
break;
|
|
default:
|
|
screenRez = GR_RESOLUTION_640x480;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Override Screen resolution with environment variables
|
|
if(GETENV(("SSTV2_SCREENREFRESH"))) {
|
|
FxU32 refreshRateEnv = ATOI(GETENV(("SSTV2_SCREENREFRESH")));
|
|
|
|
switch(refreshRateEnv) {
|
|
case 75:
|
|
refreshRate = GR_REFRESH_75Hz;
|
|
break;
|
|
case 85:
|
|
refreshRate = GR_REFRESH_85Hz;
|
|
break;
|
|
case 120:
|
|
refreshRate = GR_REFRESH_120Hz;
|
|
break;
|
|
default:
|
|
refreshRate = GR_REFRESH_60Hz;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch(screenRez) {
|
|
|
|
case(GR_RESOLUTION_512x256):
|
|
return(&SST_VREZ_512X256_60);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_512x384):
|
|
|
|
if( GETENV( ("SSTV2_REFRESH_512x384") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_512x384") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_120Hz)
|
|
return(&SST_VREZ_512X384_120);
|
|
else if(refreshRate == GR_REFRESH_85Hz) {
|
|
if(sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_512X384_85_NOSCANDOUBLE);
|
|
else
|
|
return(&SST_VREZ_512X384_85);
|
|
} else if(refreshRate == GR_REFRESH_75Hz) {
|
|
if(sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_512X384_75_NOSCANDOUBLE);
|
|
else
|
|
return(&SST_VREZ_512X384_75);
|
|
} else {
|
|
if(sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_512X384_72);
|
|
else
|
|
return(&SST_VREZ_512X384_60);
|
|
}
|
|
break;
|
|
|
|
case(GR_RESOLUTION_640x400):
|
|
|
|
if( GETENV( ("SSTV2_REFRESH_640x400") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_640x400") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_120Hz)
|
|
return(&SST_VREZ_640X400_120);
|
|
else if(refreshRate == GR_REFRESH_85Hz)
|
|
return(&SST_VREZ_640X400_85);
|
|
else if(refreshRate == GR_REFRESH_75Hz)
|
|
return(&SST_VREZ_640X400_75);
|
|
else
|
|
return(&SST_VREZ_640X400_70);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_640x480):
|
|
|
|
if( GETENV( ("SSTV2_REFRESH_640x480") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_640x480") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_120Hz)
|
|
return(&SST_VREZ_640X480_120);
|
|
else if(refreshRate == GR_REFRESH_85Hz)
|
|
return(&SST_VREZ_640X480_85);
|
|
else if(refreshRate == GR_REFRESH_75Hz)
|
|
return(&SST_VREZ_640X480_75);
|
|
else
|
|
return(&SST_VREZ_640X480_60);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_800x600):
|
|
|
|
if( GETENV( ("SSTV2_REFRESH_800x600") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_800x600") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_120Hz)
|
|
return(&SST_VREZ_800X600_120);
|
|
else if(refreshRate == GR_REFRESH_85Hz)
|
|
return(&SST_VREZ_800X600_85);
|
|
else if(refreshRate == GR_REFRESH_75Hz)
|
|
return(&SST_VREZ_800X600_75);
|
|
else
|
|
return(&SST_VREZ_800X600_60);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_856x480):
|
|
return(&SST_VREZ_856X480_60);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_960x720):
|
|
if( GETENV( ("SSTV2_REFRESH_960x720") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_960x720") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_85Hz)
|
|
return(&SST_VREZ_960X720_85);
|
|
else if(refreshRate == GR_REFRESH_75Hz)
|
|
return(&SST_VREZ_960X720_75);
|
|
else
|
|
return(&SST_VREZ_960X720_60);
|
|
break;
|
|
|
|
case(GR_RESOLUTION_1024x768):
|
|
|
|
if( GETENV( ("SSTV2_REFRESH_1024x768") ) )
|
|
refreshRate = sst1InitConvertRefreshRate( ATOI( GETENV( ("SSTV2_REFRESH_1024x768") ) ) );
|
|
|
|
if(refreshRate == GR_REFRESH_85Hz)
|
|
return(&SST_VREZ_1024X768_85);
|
|
else if(refreshRate == GR_REFRESH_75Hz)
|
|
return(&SST_VREZ_1024X768_75);
|
|
else
|
|
return(&SST_VREZ_1024X768_60);
|
|
break;
|
|
|
|
#ifdef H3D
|
|
/* In the following cases, sli can't handle line doubled LD modes */
|
|
/* therefore, we need to return a non-line doubled mode if we're */
|
|
/* sli-ing */
|
|
|
|
case (GR_RESOLUTION_640x240_AUTOFLIPPED):
|
|
case (GR_RESOLUTION_640x480_AUTOFLIPPED):
|
|
if (sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_640X960_60);
|
|
else
|
|
return(&SST_VREZ_640X960LD_60);
|
|
break;
|
|
|
|
case (GR_RESOLUTION_800x300_AUTOFLIPPED):
|
|
case (GR_RESOLUTION_800x600_AUTOFLIPPED):
|
|
if (sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_800X630_60);
|
|
else
|
|
return(&SST_VREZ_800X1200LD_45);
|
|
break;
|
|
|
|
case (GR_RESOLUTION_960x360_AUTOFLIPPED):
|
|
case (GR_RESOLUTION_960x720_AUTOFLIPPED):
|
|
if (sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_960X742_60);
|
|
else
|
|
return((sst1VideoTimingStruct *) NULL);
|
|
break;
|
|
|
|
case (GR_RESOLUTION_1024x384_AUTOFLIPPED):
|
|
case (GR_RESOLUTION_1024x768_AUTOFLIPPED):
|
|
if (sst1CurrentBoard->sliDetected)
|
|
return(&SST_VREZ_1024X768_60);
|
|
else
|
|
return((sst1VideoTimingStruct *) NULL);
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
INIT_PRINTF(("sst1InitFindVideoTimingStruc(): Unsupported Resolution...\n"));
|
|
return((sst1VideoTimingStruct *) NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
FxU32 sst1InitConvertRefreshRate( FxU32 refreshRate )
|
|
{
|
|
switch( refreshRate )
|
|
{
|
|
case 75:
|
|
return( GR_REFRESH_75Hz );
|
|
case 85:
|
|
return( GR_REFRESH_85Hz );
|
|
case 120:
|
|
return( GR_REFRESH_120Hz );
|
|
default:
|
|
return( GR_REFRESH_60Hz );
|
|
}
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitMonitorDetect()
|
|
** Detect whether or not a monitor is connected to the board
|
|
**
|
|
*/
|
|
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitMonitorDetect(FxU32 *sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 gammaArray[32];
|
|
FxU32 j, k;
|
|
FxU32 gammaCorrectConstant = 0x5c;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
/* check to see if we are a single board SLI slave, and if
|
|
* so, then don't detect a monitor - jeske
|
|
*/
|
|
//if (sst1CurrentBoard->singleBrdSLISlave) {
|
|
// sst1CurrentBoard->monitorDetected = 0;
|
|
// return (FXTRUE);
|
|
// }
|
|
|
|
if(GETENV(("SSTV2_MDETECT_CONST"))) {
|
|
SSCANF(GETENV(("SSTV2_MDETECT_CONST")), "%ld", &gammaCorrectConstant);
|
|
INIT_PRINTF(("sst1InitMonitorDetect(): Using value 0x%x for constant gamma value...\n", gammaCorrectConstant));
|
|
}
|
|
|
|
// Force gamma to always output clearColor value...
|
|
for(j=0; j<32; j++)
|
|
gammaArray[j] = gammaCorrectConstant;
|
|
//gammaArray[j] = 0xff; // 0xff never detects monitor...
|
|
//gammaArray[j] = 0x0; // 0x0 always detects monitor...
|
|
sst1InitGammaTable(sstbase, 32, gammaArray, gammaArray, gammaArray);
|
|
|
|
// Wait for for monitor to sync...
|
|
sst1InitIdle(sstbase);
|
|
for(k=0; k<(sst1CurrentBoard->fbiVideoRefresh>>2); k++) {
|
|
// Wait for inactive vsync...
|
|
do {
|
|
j = IGET(sst->status);
|
|
} while(!(j & SST_VRETRACE));
|
|
|
|
// Wait for active vsync
|
|
do {
|
|
j = IGET(sst->status);
|
|
} while(j & SST_VRETRACE);
|
|
}
|
|
|
|
while(1) {
|
|
FxU32 firstInit6 = IGET(sst->fbiInit6) & SST_GPIO_3;
|
|
FxU32 hvRetrace = IGET(sst->hvRetrace);
|
|
FxU32 vBeam = hvRetrace & 0x1fff;
|
|
FxU32 hBeam = (hvRetrace>>16) & 0x7ff;
|
|
FxU32 secondInit6 = IGET(sst->fbiInit6) & SST_GPIO_3;
|
|
|
|
if((vBeam > (sst1CurrentBoard->fbiVideoStruct->vBackPorch + 10)) &&
|
|
(vBeam < (sst1CurrentBoard->fbiVideoStruct->vBackPorch +
|
|
sst1CurrentBoard->fbiVideoHeight - 10)) &&
|
|
(hBeam > (sst1CurrentBoard->fbiVideoStruct->hBackPorch +
|
|
sst1CurrentBoard->fbiVideoStruct->hSyncOn + 10)) &&
|
|
(hBeam < (sst1CurrentBoard->fbiVideoStruct->hBackPorch +
|
|
sst1CurrentBoard->fbiVideoStruct->hSyncOn +
|
|
sst1CurrentBoard->fbiVideoWidth - 10))) {
|
|
if(firstInit6 == secondInit6) {
|
|
if(firstInit6)
|
|
sst1CurrentBoard->monitorDetected = 1;
|
|
else
|
|
sst1CurrentBoard->monitorDetected = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Override with environment variable...
|
|
if(GETENV(("SSTV2_MDETECT")))
|
|
sst1CurrentBoard->monitorDetected =
|
|
(ATOI(GETENV(("SSTV2_MDETECT")))) ? 1 : 0;
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitSetClkDelays():
|
|
** Calculate FT, TF0, and TF1 clock delay values...
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitSetClkDelays(FxU32 *sstbase)
|
|
{
|
|
FxU32 tf0_clkdel, tf1_clkdel, tf2_clkdel, ft_clkdel;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(sst1CurrentBoard->fbiBoardID == 0x3) {
|
|
// Early 4-layer 4220 board -- Runs at 83 MHz by default...
|
|
if(sst1CurrentBoard->fbiGrxClkFreq <= 80) {
|
|
ft_clkdel = 0x5;
|
|
tf0_clkdel = 0x7;
|
|
tf1_clkdel = 0x8;
|
|
tf2_clkdel = 0x8;
|
|
} else {
|
|
ft_clkdel = 0x4;
|
|
tf0_clkdel = 0x6;
|
|
tf1_clkdel = 0x7;
|
|
tf2_clkdel = 0x7;
|
|
}
|
|
goto setDelays;
|
|
}
|
|
|
|
if(GETENV(("SSTV2_IGNORE_CLKDELAYS"))) {
|
|
INIT_PRINTF(("sst1InitSetClkDelays() WARNING: Bypassing dynamic clock delay detection...\n"));
|
|
ft_clkdel = 0x4;
|
|
tf0_clkdel = 0x6;
|
|
tf1_clkdel = 0x6;
|
|
tf2_clkdel = 0x6;
|
|
goto setDelays;
|
|
}
|
|
|
|
// FT Clock Delay...
|
|
if(sst1CurrentBoard->fbiNandTree < 5000)
|
|
// Account for very slow processes...
|
|
ft_clkdel = 0x3;
|
|
else
|
|
ft_clkdel = 0x4;
|
|
|
|
{
|
|
const char
|
|
*tf2Str = GETENV("SSTV2_INIT_TF2_RESET_DELAY"),
|
|
*tf1Str = GETENV("SSTV2_INIT_TF1_RESET_DELAY"),
|
|
*tf0Str = GETENV("SSTV2_INIT_TF0_RESET_DELAY");
|
|
const FxU32
|
|
tf2 = ((tf2Str == NULL) ? 11 : atoi(tf2Str)),
|
|
tf1 = ((tf1Str == NULL) ? 11 : atoi(tf1Str)),
|
|
tf0 = ((tf0Str == NULL) ? 9 : atoi(tf0Str));
|
|
|
|
// TF2 Clock Delay...
|
|
if(sst1CurrentBoard->numberTmus > 2) {
|
|
if(sst1InitCalcTClkDelay(sstbase, 2, tf2) == FXTRUE)
|
|
// Test failed. Fast process TMUs...
|
|
tf2_clkdel = 0x7;
|
|
else
|
|
tf2_clkdel = 0x6;
|
|
} else
|
|
tf2_clkdel = 0x6;
|
|
|
|
// TF1 Clock Delay...
|
|
if(sst1CurrentBoard->numberTmus > 1) {
|
|
if(sst1InitCalcTClkDelay(sstbase, 1, tf1) == FXTRUE)
|
|
// Test failed. Fast process TMUs...
|
|
tf1_clkdel = 0x7;
|
|
else
|
|
tf1_clkdel = 0x6;
|
|
} else
|
|
tf1_clkdel = 0x6;
|
|
|
|
// Reset FBI & TMU, and put TF1 clock delay value back to default...
|
|
if(sst1InitResetTmus(sstbase) == FXFALSE) {
|
|
INIT_PRINTF(("sst1InitSetClkDelays() ERROR(1): Could not reset TMUs...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
|
|
// TF0 Clock Delay...
|
|
if(sst1InitCalcTClkDelay(sstbase, 0, tf0) == FXTRUE)
|
|
// Test failed. Fast process TMUs...
|
|
tf0_clkdel = 0x7;
|
|
else
|
|
tf0_clkdel = 0x6;
|
|
}
|
|
|
|
// Reset FBI & TMU, and put TF0 clock delay value back to default...
|
|
if(sst1InitResetTmus(sstbase) == FXFALSE) {
|
|
INIT_PRINTF(("sst1InitSetClkDelays() ERROR(2): Could not reset TMUs...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
|
|
// Adjust for lower frequencies...
|
|
if(sst1CurrentBoard->fbiGrxClkFreq < 80) {
|
|
ft_clkdel++;
|
|
tf0_clkdel++;
|
|
tf1_clkdel++;
|
|
tf2_clkdel++;
|
|
}
|
|
|
|
setDelays:
|
|
|
|
// Override with environment variables
|
|
if(GETENV(("SSTV2_FT_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_FT_CLKDEL")), "%ld", &ft_clkdel);
|
|
if(GETENV(("SSTV2_TF0_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_TF0_CLKDEL")), "%ld", &tf0_clkdel);
|
|
if(GETENV(("SSTV2_TF1_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_TF1_CLKDEL")), "%ld", &tf1_clkdel);
|
|
if(GETENV(("SSTV2_TF2_CLKDEL")))
|
|
SSCANF(GETENV(("SSTV2_TF2_CLKDEL")), "%ld", &tf2_clkdel);
|
|
|
|
INIT_PRINTF(("sst1InitSetClkDelays(): Setting FBI-to-TREX clock delay to 0x%x...\n", ft_clkdel));
|
|
INIT_PRINTF(("sst1InitSetClkDelays(): Setting TREX#0 TREX-to-FBI clock delay to 0x%x\n",
|
|
tf0_clkdel));
|
|
INIT_PRINTF(("sst1InitSetClkDelays(): Setting TREX#1 TREX-to-FBI clock delay to 0x%x\n",
|
|
tf1_clkdel));
|
|
INIT_PRINTF(("sst1InitSetClkDelays(): Setting TREX#2 TREX-to-FBI clock delay to 0x%x\n",
|
|
tf2_clkdel));
|
|
|
|
ISET(sst->fbiInit3, (IGET(sst->fbiInit3) & ~SST_FT_CLK_DEL_ADJ) |
|
|
(ft_clkdel << SST_FT_CLK_DEL_ADJ_SHIFT));
|
|
sst1InitIdleFBINoNOP(sstbase);
|
|
|
|
sst1CurrentBoard->tmuInit1[0] = (sst1CurrentBoard->tmuInit1[0] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf0_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
sst1CurrentBoard->tmuInit1[1] = (sst1CurrentBoard->tmuInit1[1] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf1_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
sst1CurrentBoard->tmuInit1[2] = (sst1CurrentBoard->tmuInit1[2] &
|
|
~SST_TEX_TF_CLK_DEL_ADJ) | (tf2_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
|
|
|
|
// Calling sst1InitResetTmus() will put the new trexinit values in the
|
|
// TMUs, as well as reset FBI and TMU...
|
|
if(sst1InitResetTmus(sstbase) == FXFALSE) {
|
|
INIT_PRINTF(("sst1InitSetClkDelays() ERROR(3): Could not reset TMUs...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
#pragma optimize ("",on)
|
|
#endif
|