diff options
Diffstat (limited to 'src/savage_streams.c')
-rw-r--r-- | src/savage_streams.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/src/savage_streams.c b/src/savage_streams.c new file mode 100644 index 0000000..88936e3 --- /dev/null +++ b/src/savage_streams.c @@ -0,0 +1,461 @@ +#include "Xv.h" +#include "dix.h" +#include "dixstruct.h" + +#include "savage_driver.h" +#include "savage_streams.h" + +#define STREAMS_TRACE 4 + +static void SavageInitStreamsOld(ScrnInfoPtr pScrn); +static void SavageInitStreamsNew(ScrnInfoPtr pScrn); + +static void OverlayParamInit(ScrnInfoPtr pScrn); +static void InitStreamsForExpansion(ScrnInfoPtr pScrn); + +static void +SavageInitSecondaryStreamOld(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + vgaHWPtr hwp; + unsigned short vgaIOBase, vgaCRIndex, vgaCRReg; + int offset = (psav->FBStart2nd - psav->FBStart); + int colorkey = pScrn->colorKey; + int pitch = pScrn->displayWidth * DEPTH_BPP(DEPTH_2ND(pScrn))/8; + CARD8 cr92; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + vgaIOBase = hwp->IOBase; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + OUTREG(COL_CHROMA_KEY_CONTROL_REG, 0x37000000 | (colorkey & 0xFF)); + OUTREG(CHROMA_KEY_UPPER_BOUND_REG, 0x00000000 | (colorkey & 0xFF)); + OUTREG(BLEND_CONTROL_REG, 0x05000000 ); + OUTREG(SSTREAM_CONTROL_REG, SSTREAMS_MODE(DEPTH_BPP(DEPTH_2ND(pScrn))) + << 24 | pScrn->displayWidth ); + OUTREG(SSTREAM_STRETCH_REG, 1 << 15); + OUTREG(SSTREAM_VSCALE_REG, 1 << 15); + OUTREG(SSTREAM_LINES_REG, pScrn->virtualY ); + OUTREG(SSTREAM_VINITIAL_REG, 0 ); + OUTREG(SSTREAM_FBADDR0_REG, offset & 0x1ffffff & ~BASE_PAD); + OUTREG(SSTREAM_FBADDR1_REG, 0 ); + + OUTREG(SSTREAM_STRIDE_REG, pitch); + OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(0,0)); + OUTREG(SSTREAM_WINDOW_SIZE_REG, + OS_WH(pScrn->displayWidth, pScrn->virtualY)); + + pitch = (pitch + 7) / 8; + VGAOUT8(vgaCRIndex, 0x92); + cr92 = VGAIN8(vgaCRReg); + VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); + VGAOUT8(vgaCRIndex, 0x93); + VGAOUT8(vgaCRReg, pitch); + OUTREG(STREAMS_FIFO_REG, 2 | 25 << 5 | 32 << 11); +} + +static void +SavageInitSecondaryStreamNew(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + vgaHWPtr hwp; + unsigned short vgaIOBase, vgaCRIndex, vgaCRReg; + int offset = (psav->FBStart2nd - psav->FBStart); + int colorkey = pScrn->colorKey; + int pitch = pScrn->displayWidth * DEPTH_BPP(DEPTH_2ND(pScrn))/8; + CARD8 cr92; + + hwp = VGAHWPTR(pScrn); + + vgaHWGetIOBase(hwp); + vgaIOBase = hwp->IOBase; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + OUTREG( SEC_STREAM_CKEY_LOW, 0x47000000 | (colorkey & 0xFF)); + OUTREG( SEC_STREAM_CKEY_UPPER, 0x47000000 | (colorkey & 0xFF)); + OUTREG( BLEND_CONTROL, SSTREAMS_MODE(DEPTH_BPP(DEPTH_2ND(pScrn))) << 9 + | 0x08 ); + if( psav->Chipset == S3_SAVAGE2000 ) { + OUTREG(SEC_STREAM_HSCALING, 1 << 15); + OUTREG(SEC_STREAM_HSCALE_NORMALIZE, 2048 << 16 ); + OUTREG(SEC_STREAM_VSCALING, 1 << 15); + } else { + OUTREG(SEC_STREAM_HSCALING,((pScrn->displayWidth &0xfff)<<20) | 1<<15); + /* BUGBUG need to add 00040000 if src stride > 2048 */ + OUTREG(SEC_STREAM_VSCALING,((pScrn->virtualY &0xfff)<<20) | 1<<15); + } + + OUTREG(SEC_STREAM_FBUF_ADDR0, offset & (0x7ffffff & ~BASE_PAD)); + OUTREG(SEC_STREAM_STRIDE, pitch); + OUTREG(SEC_STREAM_WINDOW_START, OS_XY(0,0)); + /* ? width may need to be increased by 1 */ + OUTREG(SEC_STREAM_WINDOW_SZ, OS_WH(pScrn->displayWidth, pScrn->virtualY)); + + pitch = (pitch + 7) / 8; + VGAOUT8(vgaCRIndex, 0x92); + cr92 = VGAIN8(vgaCRReg); + VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); + VGAOUT8(vgaCRIndex, 0x93); + VGAOUT8(vgaCRReg, pitch); +} + +void +SavageInitSecondaryStream(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + + if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || + (psav->Chipset == S3_SUPERSAVAGE) || + (psav->Chipset == S3_SAVAGE2000) ) + SavageInitSecondaryStreamNew(pScrn); + else + SavageInitSecondaryStreamOld(pScrn); +} + +void SavageInitStreamsOld(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + unsigned long jDelta; + unsigned long format = 0; + + /* + * For the OLD streams engine, several of these registers + * cannot be touched unless streams are on. Seems backwards to me; + * I'd want to set 'em up, then cut 'em loose. + */ + + xf86ErrorFVerb(STREAMS_TRACE, "SavageInitStreams\n" ); + + /* Primary stream reflects the frame buffer. */ + + if (psav->FBStart2nd) { + jDelta = pScrn->displayWidth; + format = 0 << 24; + } else { + jDelta = pScrn->displayWidth * (pScrn->bitsPerPixel + 7) / 8; + switch( pScrn->depth ) { + case 8: format = 0 << 24; break; + case 15: format = 3 << 24; break; + case 16: format = 5 << 24; break; + case 24: format = 7 << 24; break; + } + } + + OUTREG( PSTREAM_WINDOW_START_REG, OS_XY(0,0) ); + OUTREG( PSTREAM_WINDOW_SIZE_REG, OS_WH(pScrn->displayWidth, pScrn->virtualY) ); + OUTREG( PSTREAM_FBADDR0_REG, pScrn->fbOffset ); + OUTREG( PSTREAM_FBADDR1_REG, 0 ); + OUTREG( PSTREAM_STRIDE_REG, jDelta ); + OUTREG( PSTREAM_CONTROL_REG, format ); + OUTREG( PSTREAM_FBSIZE_REG, jDelta * pScrn->virtualY >> 3 ); + + OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 ); + OUTREG( SSTREAM_CONTROL_REG, 0 ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 ); + OUTREG( SSTREAM_STRETCH_REG, 0 ); + OUTREG( COLOR_ADJUSTMENT_REG, 0 ); + OUTREG( BLEND_CONTROL_REG, 1 << 24 ); + OUTREG( DOUBLE_BUFFER_REG, 0 ); + OUTREG( SSTREAM_FBADDR0_REG, 0 ); + OUTREG( SSTREAM_FBADDR1_REG, 0 ); + OUTREG( SSTREAM_FBADDR2_REG, 0 ); +/* OUTREG( SSTREAM_FBSIZE_REG, 0 ); */ + OUTREG( SSTREAM_STRIDE_REG, 0 ); + OUTREG( SSTREAM_VSCALE_REG, 0 ); + OUTREG( SSTREAM_LINES_REG, 0 ); + OUTREG( SSTREAM_VINITIAL_REG, 0 ); + OUTREG( SSTREAM_WINDOW_START_REG, OS_XY(0xfffe, 0xfffe) ); + OUTREG( SSTREAM_WINDOW_SIZE_REG, OS_WH(10,2) ); + OUTREG(STREAMS_FIFO_REG, 2 | 25 << 5 | 32 << 11); + + { + vgaHWPtr hwp; + unsigned short vgaIOBase, vgaCRIndex, vgaCRReg; + unsigned char cr90; + + hwp = VGAHWPTR(pScrn); + + vgaHWGetIOBase(hwp); + vgaIOBase = hwp->IOBase; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + VGAOUT8(vgaCRIndex, 0x90); + cr90 = VGAIN8(vgaCRReg); + VGAOUT8(vgaCRReg, (cr90 & 0x7F)); + } +} + +static void +SavageInitStreamsNew(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + unsigned long jDelta; + + xf86ErrorFVerb(STREAMS_TRACE, "SavageInitStreams\n" ); + + if( + S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && + !psav->CrtOnly && + !psav->TvOn + ) { + OverlayParamInit( pScrn ); + } + + /* Primary stream reflects the frame buffer. */ + + if (psav->FBStart2nd) + jDelta = pScrn->displayWidth; + else + jDelta = pScrn->displayWidth * (pScrn->bitsPerPixel + 7) / 8; + + OUTREG( PRI_STREAM_BUFFERSIZE, jDelta * pScrn->virtualY >> 3 ); + OUTREG( PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset ); + OUTREG( PRI_STREAM_STRIDE, jDelta ); + + OUTREG( SEC_STREAM_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); + OUTREG( SEC_STREAM_HSCALING, 0 ); + OUTREG( SEC_STREAM_VSCALING, 0 ); + OUTREG( BLEND_CONTROL, 0 ); + OUTREG( SEC_STREAM_FBUF_ADDR0, 0 ); + OUTREG( SEC_STREAM_FBUF_ADDR1, 0 ); + OUTREG( SEC_STREAM_FBUF_ADDR2, 0 ); + OUTREG( SEC_STREAM_WINDOW_START, 0 ); + OUTREG( SEC_STREAM_WINDOW_SZ, 0 ); +/* OUTREG( SEC_STREAM_BUFFERSIZE, 0 ); */ + OUTREG( SEC_STREAM_TILE_OFF, 0 ); + OUTREG( SEC_STREAM_OPAQUE_OVERLAY, 0 ); + OUTREG( SEC_STREAM_STRIDE, 0 ); + + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, 0x01F1547E ); +#if 0 + { + vgaHWPtr hwp; + unsigned short vgaIOBase, vgaCRIndex, vgaCRReg; + hwp = VGAHWPTR(pScrn); + unsigned char cr90; + + vgaHWGetIOBase(hwp); + vgaIOBase = hwp->IOBase; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + VGAOUT8(vgaCRIndex, 0x90); + cr90 = VGAIN8(vgaCRReg); + VGAOUT8(vgaCRReg, (cr90 & 0x7F)); + } +#endif +} + + +/* Function to get lcd factor, display offset for overlay use + * Input: pScrn; Output: x,yfactor, displayoffset in pScrn + */ +static void OverlayParamInit(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + + psav = SAVPTR(pScrn); + psav->cxScreen = pScrn->currentMode->HDisplay; + InitStreamsForExpansion(pScrn); +} + +/* Function to calculate lcd expansion x,y factor and offset for overlay + */ +static void InitStreamsForExpansion(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + int PanelSizeX,PanelSizeY; + int ViewPortWidth,ViewPortHeight; + int XExpansion, YExpansion; + int XFactor, YFactor; + int Hstate, Vstate; + + static CARD32 Xfactors[] = { + 0x00010001, + 0x00010001, /* 1 */ + 0, + 0x00090008, /* 3 */ + 0x00050004, /* 4 */ + 0, + 0x00030002, /* 6 */ + 0x00020001 /* 7 */ + }; + + static CARD32 Yfactors[] = { + 0x00010001, 0x00010001, + 0, 0x00060005, + 0x00050004, 0x00040003, + 0, 0x00030002, + 0x00020001, 0x00050002, + 0x000C0005, 0x00080003, + 0x00090004, 0, + 0x00030001, 0x00040001, + }; + + + + PanelSizeX = psav->PanelX; + PanelSizeY = psav->PanelY; + ViewPortWidth = pScrn->currentMode->HDisplay; + ViewPortHeight = pScrn->currentMode->VDisplay; + + if( PanelSizeX == 1408 ) + PanelSizeX = 1400; + + XExpansion = 0x00010001; + YExpansion = 0x00010001; + + psav->displayXoffset = 0; + psav->displayYoffset = 0; + + VGAOUT8(0x3C4, HZEXP_COMP_1); + Hstate = VGAIN8(0x3C5); + VGAOUT8(0x3C4, VTEXP_COMP_1); + Vstate = VGAIN8(0x3C5); + VGAOUT8(0x3C4, HZEXP_FACTOR_IGA1); + XFactor = VGAIN8(0x3C5); + VGAOUT8(0x3C4, VTEXP_FACTOR_IGA1); + YFactor = VGAIN8(0x3C5); + + if( Hstate & EC1_EXPAND_ON ) + { + XExpansion = Xfactors[XFactor>>4]; + } + + if( Vstate & EC1_EXPAND_ON ) + { + YExpansion = Yfactors[YFactor>>4]; + } + + psav->XExp1 = XExpansion >> 16; + psav->XExp2 = XExpansion & 0xFFFF; + + psav->YExp1 = YExpansion >> 16; + psav->YExp2 = YExpansion & 0xFFFF; + + psav->displayXoffset = + ((PanelSizeX - (psav->XExp1 * ViewPortWidth) / psav->XExp2) / 2 + 7) & 0xfff8; + psav->displayYoffset = + ((PanelSizeY - (psav->YExp1 * ViewPortHeight) / psav->YExp2) / 2); + +} /* InitStreamsForExpansionPM */ + +void +SavageStreamsOn(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + unsigned char jStreamsControl; + unsigned short vgaCRIndex = psav->vgaIOBase + 4; + unsigned short vgaCRReg = psav->vgaIOBase + 5; + + xf86ErrorFVerb(STREAMS_TRACE, "SavageStreamsOn\n" ); + + /* Sequence stolen from streams.c in M7 NT driver */ + + + xf86EnableIO(); + + /* Unlock extended registers. */ + + VGAOUT16(vgaCRIndex, 0x4838); + VGAOUT16(vgaCRIndex, 0xa039); + VGAOUT16(0x3c4, 0x0608); + + VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); + + if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || +#if 0 /* I don't think commenting this out is correct (EE) */ + (psav->Chipset == S3_SUPERSAVAGE) || +#endif + (psav->Chipset == S3_SAVAGE2000) ) + { + SavageInitStreamsNew( pScrn ); + + jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAM1; + + /* Wait for VBLANK. */ + + VerticalRetraceWait(psav); + + /* Fire up streams! */ + + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, 0x01F1547E ); + } + else + { + jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAMS_OLD; + + /* Wait for VBLANK. */ + + VerticalRetraceWait(psav); + + /* Fire up streams! */ + + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + + SavageInitStreamsOld( pScrn ); + } + + /* Wait for VBLANK. */ + + VerticalRetraceWait(psav); + + /* Turn on secondary stream TV flicker filter, once we support TV. */ + + /* SR70 |= 0x10 */ + +} + +void +SavageStreamsOff(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + unsigned char jStreamsControl; + unsigned short vgaCRIndex = psav->vgaIOBase + 4; + unsigned short vgaCRReg = psav->vgaIOBase + 5; + + xf86ErrorFVerb(STREAMS_TRACE, "SavageStreamsOff\n" ); + + xf86EnableIO(); + + /* Unlock extended registers. */ + + VGAOUT16(vgaCRIndex, 0x4838); + VGAOUT16(vgaCRIndex, 0xa039); + VGAOUT16(0x3c4, 0x0608); + + VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); + if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || + (psav->Chipset == S3_SUPERSAVAGE) || + (psav->Chipset == S3_SAVAGE2000) ) + jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS; + else + jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS_OLD; + + /* Wait for VBLANK. */ + + VerticalRetraceWait(psav); + + /* Kill streams. */ + + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + + VGAOUT16( vgaCRIndex, 0x0093 ); + VGAOUT8( vgaCRIndex, 0x92 ); + VGAOUT8( vgaCRReg, VGAIN8(vgaCRReg) & 0x40 ); + +} + |