summaryrefslogtreecommitdiff
path: root/src/savage_streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/savage_streams.c')
-rw-r--r--src/savage_streams.c461
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 );
+
+}
+