diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/savage_accel.c | 284 | ||||
-rw-r--r-- | src/savage_bci.h | 2 | ||||
-rw-r--r-- | src/savage_cursor.c | 100 | ||||
-rw-r--r-- | src/savage_driver.c | 827 | ||||
-rw-r--r-- | src/savage_driver.h | 29 | ||||
-rw-r--r-- | src/savage_regs.h | 12 | ||||
-rw-r--r-- | src/savage_streams.c | 256 | ||||
-rw-r--r-- | src/savage_vbe.c | 140 | ||||
-rw-r--r-- | src/savage_vbe.h | 54 | ||||
-rw-r--r-- | src/savage_video.c | 279 |
10 files changed, 1431 insertions, 552 deletions
diff --git a/src/savage_accel.c b/src/savage_accel.c index ea79817..104fca3 100644 --- a/src/savage_accel.c +++ b/src/savage_accel.c @@ -31,6 +31,8 @@ #include "savage_dri.h" #endif +extern int gSavageEntityIndex; + /* Forward declaration of functions used in the driver */ static void SavageSetupForScreenToScreenCopy( @@ -663,24 +665,35 @@ void SavageSetGBD_M7(ScrnInfoPtr pScrn) * = 0 standard VGA address and stride registers * are used to control the primary streams */ - OUTREG8(CRT_ADDRESS_REG,0x67); - byte = INREG8(CRT_DATA_REG) | 0x08; - OUTREG8(CRT_DATA_REG,byte); - - /* IGA 2 */ - OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); - - OUTREG8(CRT_ADDRESS_REG,0x67); - byte = INREG8(CRT_DATA_REG) | 0x08; - OUTREG8(CRT_DATA_REG,byte); + if (psav->IsPrimary) { + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); + } else if (psav->IsSecondary) { + /* IGA 2 */ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); + + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); - OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); - -#if 0 + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); + } else { + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); + /* IGA 2 */ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); + } /* Set primary stream to bank 0 */ OUTREG8(CRT_ADDRESS_REG, MEMORY_CTRL0_REG);/* CRCA */ byte = INREG8(CRT_DATA_REG) & ~(MEM_PS1 + MEM_PS2) ; OUTREG8(CRT_DATA_REG,byte); +#if 0 /* * if we have 8MB of frame buffer here then we must really be a 16MB * card and that means that the second device is always in the upper @@ -694,11 +707,19 @@ void SavageSetGBD_M7(ScrnInfoPtr pScrn) #endif /* MM81C0 and 81C4 are used to control primary stream. */ - OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); - OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); - OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000); - OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000); - + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff); + OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff); + OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff); + } else { + OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff); + OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff); + OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff); + OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff); + } + /* * Program Primary Stream Stride Register. * @@ -710,28 +731,59 @@ void SavageSetGBD_M7(ScrnInfoPtr pScrn) * bytes padded up to an even number of tilewidths. */ if (!psav->bTiled) { - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) | + (psav->lDelta & 0x00003fff)); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) | + (psav->lDelta & 0x00003fff)); + } else { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | (psav->lDelta & 0x00003fff)); - OUTREG32(PRI_STREAM2_STRIDE, + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | (psav->lDelta & 0x00003fff)); + } + } else if (pScrn->bitsPerPixel == 16) { /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */ - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0x80000000 | (psav->lDelta & 0x00003fff)); - OUTREG32(PRI_STREAM2_STRIDE, + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0x80000000 | (psav->lDelta & 0x00003fff)); - + } else { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0x80000000 | (psav->lDelta & 0x00003fff)); + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0x80000000 | (psav->lDelta & 0x00003fff)); + } + } else if (pScrn->bitsPerPixel == 32) { - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0xC0000000 | (psav->lDelta & 0x00003fff)); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0xC0000000 | (psav->lDelta & 0x00003fff)); - OUTREG32(PRI_STREAM2_STRIDE, + } else { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0xC0000000 | (psav->lDelta & 0x00003fff)); + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0xC0000000 | (psav->lDelta & 0x00003fff)); + } } OUTREG32(0x8128, 0xFFFFFFFFL); @@ -790,20 +842,26 @@ void SavageSetGBD_M7(ScrnInfoPtr pScrn) psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* 16 bit */ ulTmp = ((psav->lDelta / 2) >> 6) << 24; - OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16); + if (psav->IsSecondary) + OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset); + else + OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset); } else if (pScrn->bitsPerPixel == 32) { psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* 32 bit */ ulTmp = ((psav->lDelta / 4) >> 5) << 24; - OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32); + if (psav->IsSecondary) + OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset); + else + OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset); } psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */ /* HW uses width */ psav->GlobalBD.bd1.HighPart.Stride = (ushort)(psav->lDelta / (pScrn->bitsPerPixel >> 3)); psav->GlobalBD.bd1.HighPart.Bpp = (uchar) (pScrn->bitsPerPixel); - psav->GlobalBD.bd1.Offset = 0; + psav->GlobalBD.bd1.Offset = pScrn->fbOffset; /* @@ -811,9 +869,14 @@ void SavageSetGBD_M7(ScrnInfoPtr pScrn) * bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window * at A000:0. */ +#if 0 OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */ byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000)); OUTREG8(CRT_DATA_REG,byte); +#endif + OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */ + byte = (INREG8(CRT_DATA_REG) | 0x04) & 0xFE; + OUTREG8(CRT_DATA_REG,byte); /* program the GBD and SBD's */ OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart ); @@ -860,18 +923,32 @@ void SavageSetGBD_PM(ScrnInfoPtr pScrn) * = 0 standard VGA address and stride registers * are used to control the primary streams */ - OUTREG8(CRT_ADDRESS_REG,0x67); - byte = INREG8(CRT_DATA_REG) | 0x08; - OUTREG8(CRT_DATA_REG,byte); + if (psav->IsPrimary) { + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); + } else if (psav->IsSecondary) { + /* IGA 2 */ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); + + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); - /* IGA 2 */ - OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); - - OUTREG8(CRT_ADDRESS_REG,0x67); - byte = INREG8(CRT_DATA_REG) | 0x08; - OUTREG8(CRT_DATA_REG,byte); + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); + } else { + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); + /* IGA 2 */ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); + + OUTREG8(CRT_ADDRESS_REG,0x67); + byte = INREG8(CRT_DATA_REG) | 0x08; + OUTREG8(CRT_DATA_REG,byte); - OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); + } /* * load ps1 active registers as determined by MM81C0/81C4 @@ -892,37 +969,73 @@ void SavageSetGBD_PM(ScrnInfoPtr pScrn) * bytes padded up to an even number of tilewidths. */ if (!psav->bTiled) { - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) | + (psav->lDelta & 0x00001fff)); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) | + (psav->lDelta & 0x00001fff)); + } else { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | (psav->lDelta & 0x00001fff)); - OUTREG32(PRI_STREAM2_STRIDE, + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | (psav->lDelta & 0x00001fff)); + } } else if (pScrn->bitsPerPixel == 16) { /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */ - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0x80000000 | (psav->lDelta & 0x00001fff)); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0x80000000 | (psav->lDelta & 0x00001fff)); - OUTREG32(PRI_STREAM2_STRIDE, + } else { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0x80000000 | (psav->lDelta & 0x00001fff)); + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0x80000000 | (psav->lDelta & 0x00001fff)); + } } else if (pScrn->bitsPerPixel == 32) { - OUTREG32(PRI_STREAM_STRIDE, + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0xC0000000 | (psav->lDelta & 0x00001fff)); - OUTREG32(PRI_STREAM2_STRIDE, + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_STRIDE, (((psav->lDelta * 2) << 16) & 0x3FFF0000) | 0xC0000000 | (psav->lDelta & 0x00001fff)); + } else { + OUTREG32(PRI_STREAM_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0xC0000000 | (psav->lDelta & 0x00001fff)); + OUTREG32(PRI_STREAM2_STRIDE, + (((psav->lDelta * 2) << 16) & 0x3FFF0000) + | 0xC0000000 | (psav->lDelta & 0x00001fff)); + } } /* MM81C0 and 81C4 are used to control primary stream. */ - /*OUTREG32(PRI_STREAM_FBUF_ADDR0,0x80000000);*/ - OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); - OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); - /*OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x80000000);*/ - OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000); - OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000); + if (psav->IsPrimary) { + OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset); + OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000); + } else if (psav->IsSecondary) { + OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000); + OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc); + } else { + OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset); + OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000); + OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000); + OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc); + } OUTREG32(0x8128, 0xFFFFFFFFL); OUTREG32(0x812C, 0xFFFFFFFFL); @@ -948,20 +1061,26 @@ void SavageSetGBD_PM(ScrnInfoPtr pScrn) psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* tile format destination */ ulTmp = (((pScrn->virtualX + 0x3f) & 0x0000ffc0) >> 6) << 20; - OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16); + if (psav->IsSecondary) + OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>5)); /* 5 or 6? */ + else + OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>5)); /* 5 or 6? */ } else if (pScrn->bitsPerPixel == 32) { psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* tile format destination */ ulTmp = (((pScrn->virtualX + 0x1f) & 0x0000ffe0) >> 5) << 20; - OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32); + if (psav->IsSecondary) + OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>5)); /* 5 or 6? */ + else + OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>5)); /* 5 or 6? */ } psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */ /* HW uses width */ psav->GlobalBD.bd1.HighPart.Stride = (ushort)(psav->lDelta / (pScrn->bitsPerPixel >> 3)); psav->GlobalBD.bd1.HighPart.Bpp = (uchar) (pScrn->bitsPerPixel); - psav->GlobalBD.bd1.Offset = 0; + psav->GlobalBD.bd1.Offset = pScrn->fbOffset; /* * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). @@ -980,13 +1099,53 @@ void SavageSetGBD_PM(ScrnInfoPtr pScrn) OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart); OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart); OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart); - + /* turn on screen */ OUTREG8(SEQ_ADDRESS_REG,0x01); byte = INREG8(SEQ_DATA_REG) & ~0x20; OUTREG8(SEQ_DATA_REG,byte); } +static +void SavageRestoreAccelState(ScrnInfoPtr pScrn) +{ + SavagePtr psav = SAVPTR(pScrn); + int bci_enable; + ulong cmd; + + BCI_GET_PTR; + + if (psav->Chipset == S3_SAVAGE_MX) + bci_enable = BCI_ENABLE; + else + bci_enable = BCI_ENABLE_TWISTER; + + psav->WaitIdleEmpty(psav); + + /* may only need to update the GBD */ +#if 1 + psav->WaitQueue(psav, 2); + + cmd = BCI_SET_REGISTER | 0xE0 | (2<<16); + BCI_SEND(cmd); + BCI_SEND(psav->GlobalBD.bd2.LoPart); + BCI_SEND((psav->GlobalBD.bd2.HiPart + | bci_enable | S3_LITTLE_ENDIAN | S3_BD64)); +#endif +#if 0 + /* program the GBD */ + OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart ); + OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart + | bci_enable | S3_LITTLE_ENDIAN | S3_BD64)); + OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart); + OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart); + OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart); + OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart); +#endif + + return; +} + /* Acceleration init function, sets up pointers to our accelerated functions */ Bool @@ -1040,6 +1199,21 @@ SavageInitAccel(ScreenPtr pScreen) xaaptr->Sync = SavageAccelSync; + if(xf86IsEntityShared(pScrn->entityList[0])) + { + DevUnion* pPriv; + SavageEntPtr pEnt; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gSavageEntityIndex); + pEnt = pPriv->ptr; + + /*if there are more than one devices sharing this entity, we + have to assign this call back, otherwise the XAA will be + disabled */ + if(pEnt->HasSecondary) + xaaptr->RestoreAccelState = SavageRestoreAccelState; + } + /* ScreenToScreen copies */ @@ -1230,7 +1404,7 @@ SavageInitAccel(ScreenPtr pScreen) pScrn->bitsPerPixel, widthBytes,bufferSize); - pSAVAGEDRIServer->frontOffset = 0; /* AGD: should probably be pScrn->fbOffset */ + pSAVAGEDRIServer->frontOffset = pScrn->fbOffset; /* 0 */ pSAVAGEDRIServer->frontPitch = widthBytes; /* Try for front, back, depth, and two framebuffers worth of diff --git a/src/savage_bci.h b/src/savage_bci.h index 9b0fc21..4fabcb7 100644 --- a/src/savage_bci.h +++ b/src/savage_bci.h @@ -112,6 +112,8 @@ #define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF) #define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF)) +#define BCI_SET_REGISTER 0x96000000 + #define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF) #define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF) #define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF) diff --git a/src/savage_cursor.c b/src/savage_cursor.c index 3f968eb..a6acdad 100644 --- a/src/savage_cursor.c +++ b/src/savage_cursor.c @@ -120,13 +120,22 @@ SavageHWCursorInit(ScreenPtr pScreen) return xf86InitCursor(pScreen, infoPtr); } - +/* + * Supposedly bit 2 of CR45 enables cursor two (rest of the cursor regs are shadowed via SR26), + * but I can't seem to enable it. For now it's disabled. - AGD + */ void SavageShowCursor(ScrnInfoPtr pScrn) { + SavagePtr psav = SAVPTR(pScrn); + /* Turn cursor on. */ - outCRReg( 0x45, inCRReg(0x45) | 0x01 ); + if (psav->IsSecondary) { + outCRReg( 0x45, inCRReg(0x45) | 0x04 ); /* cursor2 bit 2*/ + } else { + outCRReg( 0x45, inCRReg(0x45) | 0x01 ); + } SAVPTR(pScrn)->hwc_on = TRUE; } @@ -134,13 +143,19 @@ SavageShowCursor(ScrnInfoPtr pScrn) void SavageHideCursor(ScrnInfoPtr pScrn) { + SavagePtr psav = SAVPTR(pScrn); + /* Turn cursor off. */ if( S3_SAVAGE4_SERIES( SAVPTR(pScrn)->Chipset ) ) { waitHSync(5); } - outCRReg( 0x45, inCRReg(0x45) & 0xfe ); + if (psav->IsSecondary) { + outCRReg( 0x45, inCRReg(0x45) & 0xfb ); /* cursor2 */ + } else { + outCRReg( 0x45, inCRReg(0x45) & 0xfe ); + } SAVPTR(pScrn)->hwc_on = FALSE; } @@ -152,8 +167,16 @@ SavageLoadCursorImage( SavagePtr psav = SAVPTR(pScrn); /* Set cursor location in frame buffer. */ - outCRReg( 0x4d, (0xff & (CARD32)psav->CursorKByte)); - outCRReg( 0x4c, (0xff00 & (CARD32)psav->CursorKByte) >> 8); + if (psav->IsSecondary) { + SelectIGA2(); + /* Set cursor location in frame buffer. */ + outCRReg( 0x4d, (0xff & psav->CursorKByte)); + outCRReg( 0x4c, (0xff00 & psav->CursorKByte) >> 8); + SelectIGA1(); + } else { + outCRReg( 0x4d, (0xff & (CARD32)psav->CursorKByte)); + outCRReg( 0x4c, (0xff00 & (CARD32)psav->CursorKByte) >> 8); + } /* Upload the cursor image to the frame buffer. */ memcpy(psav->FBBase + psav->CursorKByte * 1024, src, 1024); @@ -174,6 +197,7 @@ SavageSetCursorPosition( int x, int y) { + SavagePtr psav = SAVPTR(pScrn); unsigned char xoff, yoff; if( S3_SAVAGE4_SERIES( SAVPTR(pScrn)->Chipset ) ) @@ -210,12 +234,23 @@ SavageSetCursorPosition( } /* This is the recomended order to move the cursor */ - outCRReg( 0x46, (x & 0xff00)>>8 ); - outCRReg( 0x47, (x & 0xff) ); - outCRReg( 0x49, (y & 0xff) ); - outCRReg( 0x4e, xoff ); - outCRReg( 0x4f, yoff ); - outCRReg( 0x48, (y & 0xff00)>>8 ); + if (psav->IsSecondary) { + SelectIGA2(); + outCRReg( 0x46, (x & 0xff00)>>8 ); + outCRReg( 0x47, (x & 0xff) ); + outCRReg( 0x49, (y & 0xff) ); + outCRReg( 0x4e, xoff ); + outCRReg( 0x4f, yoff ); + outCRReg( 0x48, (y & 0xff00)>>8 ); + SelectIGA1(); + } else { + outCRReg( 0x46, (x & 0xff00)>>8 ); + outCRReg( 0x47, (x & 0xff) ); + outCRReg( 0x49, (y & 0xff) ); + outCRReg( 0x4e, xoff ); + outCRReg( 0x4f, yoff ); + outCRReg( 0x48, (y & 0xff00)>>8 ); + } } @@ -243,19 +278,36 @@ SavageSetCursorColors( ) { /* Do it straight, full 24 bit color. */ - - /* Reset the cursor color stack pointer */ - inCRReg(0x45); - /* Write low, mid, high bytes - foreground */ - outCRReg(0x4a, fg); - outCRReg(0x4a, fg >> 8); - outCRReg(0x4a, fg >> 16); - /* Reset the cursor color stack pointer */ - inCRReg(0x45); - /* Write low, mid, high bytes - background */ - outCRReg(0x4b, bg); - outCRReg(0x4b, bg >> 8); - outCRReg(0x4b, bg >> 16); + if (psav->IsSecondary) { + /* cursor 2 */ + /* Reset the cursor color stack pointer */ + inCRReg(0x45); + SelectIGA2(); + /* Write low, mid, high bytes - foreground */ + outCRReg(0x4a, fg); + outCRReg(0x4a, fg >> 8); + outCRReg(0x4a, fg >> 16); + /* Reset the cursor color stack pointer */ + inCRReg(0x45); + /* Write low, mid, high bytes - background */ + outCRReg(0x4b, bg); + outCRReg(0x4b, bg >> 8); + outCRReg(0x4b, bg >> 16); + SelectIGA1(); + } else { + /* Reset the cursor color stack pointer */ + inCRReg(0x45); + /* Write low, mid, high bytes - foreground */ + outCRReg(0x4a, fg); + outCRReg(0x4a, fg >> 8); + outCRReg(0x4a, fg >> 16); + /* Reset the cursor color stack pointer */ + inCRReg(0x45); + /* Write low, mid, high bytes - background */ + outCRReg(0x4b, bg); + outCRReg(0x4b, bg >> 8); + outCRReg(0x4b, bg >> 16); + } return; } #if 0 diff --git a/src/savage_driver.c b/src/savage_driver.c index 1a7f264..6049d81 100644 --- a/src/savage_driver.c +++ b/src/savage_driver.c @@ -108,6 +108,8 @@ extern ScrnInfoPtr gpScrn; #define TRACE(prms) #endif +int gSavageEntityIndex = -1; + DriverRec SAVAGE = { SAVAGE_VERSION, @@ -217,6 +219,7 @@ typedef enum { ,OPTION_BCI_FOR_XV ,OPTION_AGP_MODE ,OPTION_AGP_SIZE + ,OPTION_DVI } SavageOpts; @@ -243,6 +246,7 @@ static const OptionInfoRec SavageOptions[] = { OPTION_BCI_FOR_XV, "BCIforXv", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_DVI, "DVI", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -426,6 +430,15 @@ static XF86ModuleVersionInfo SavageVersRec = { XF86ModuleData savageModuleData = { &SavageVersRec, SavageSetup, NULL }; +static SavageEntPtr SavageEntPriv(ScrnInfoPtr pScrn) +{ + DevUnion *pPriv; + SavagePtr psav = SAVPTR(pScrn); + pPriv = xf86GetEntityPrivate(psav->pEnt->index, + gSavageEntityIndex); + return pPriv->ptr; +} + static pointer SavageSetup(pointer module, pointer opts, int *errmaj, int *errmin) { @@ -738,25 +751,64 @@ static Bool SavageProbe(DriverPtr drv, int flags) foundScreen = TRUE; else for (i=0; i<numUsed; i++) { - ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); - - pScrn->driverVersion = SAVAGE_VERSION; - pScrn->driverName = DRIVER_NAME; - pScrn->name = "SAVAGE"; - pScrn->Probe = SavageProbe; - pScrn->PreInit = SavagePreInit; - pScrn->ScreenInit = SavageScreenInit; - pScrn->SwitchMode = SavageSwitchMode; - pScrn->AdjustFrame = SavageAdjustFrame; - pScrn->EnterVT = SavageEnterVT; - pScrn->LeaveVT = SavageLeaveVT; - pScrn->FreeScreen = NULL; - pScrn->ValidMode = SavageValidMode; - foundScreen = TRUE; - xf86ConfigActivePciEntity(pScrn, usedChips[i], SavagePciChipsets, - NULL, NULL, NULL, NULL, NULL); + EntityInfoPtr pEnt; + ScrnInfoPtr pScrn; + pScrn = NULL; + pEnt = xf86GetEntityInfo(usedChips[i]); + if((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], + SavagePciChipsets, 0, 0, 0, 0, 0))) + { + + pScrn->driverVersion = SAVAGE_VERSION; + pScrn->driverName = DRIVER_NAME; + pScrn->name = "SAVAGE"; + pScrn->Probe = SavageProbe; + pScrn->PreInit = SavagePreInit; + pScrn->ScreenInit = SavageScreenInit; + pScrn->SwitchMode = SavageSwitchMode; + pScrn->AdjustFrame = SavageAdjustFrame; + pScrn->EnterVT = SavageEnterVT; + pScrn->LeaveVT = SavageLeaveVT; + pScrn->FreeScreen = NULL; + pScrn->ValidMode = SavageValidMode; + foundScreen = TRUE; + } + + pEnt = xf86GetEntityInfo(usedChips[i]); + + /* MX, IX, SuperSavage cards support Dual-Head, mark the entity as sharable*/ + if(pEnt->chipset == S3_SAVAGE_MX || pEnt->chipset == S3_SUPERSAVAGE) + { + DevUnion *pPriv; + SavageEntPtr pSavageEnt; + + xf86SetEntitySharable(usedChips[i]); + + if (gSavageEntityIndex == -1) + gSavageEntityIndex = xf86AllocateEntityPrivateIndex(); + + pPriv = xf86GetEntityPrivate(pEnt->index, + gSavageEntityIndex); + + if (!pPriv->ptr) { + int j; + int instance = xf86GetNumEntityInstances(pEnt->index); + + for (j = 0; j < instance; j++) + xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j); + + pPriv->ptr = xnfcalloc(sizeof(SavageEntRec), 1); + pSavageEnt = pPriv->ptr; + pSavageEnt->HasSecondary = FALSE; + } else { + pSavageEnt = pPriv->ptr; + pSavageEnt->HasSecondary = TRUE; + } + } + xfree(pEnt); } + xfree(usedChips); return foundScreen; } @@ -774,6 +826,130 @@ static int LookupChipID( PciChipsets* pset, int ChipID ) return -1; } +static void SavageDoDDC(ScrnInfoPtr pScrn) +{ + SavagePtr psav= SAVPTR(pScrn); + pointer ddc; + + /* Do the DDC dance. */ /* S3/VIA's DDC code */ + ddc = xf86LoadSubModule(pScrn, "ddc"); + if (ddc) { + xf86LoaderReqSymLists(ddcSymbols, NULL); + switch( psav->Chipset ) { + case S3_SAVAGE3D: + case S3_SAVAGE_MX: + case S3_SUPERSAVAGE: + case S3_SAVAGE2000: + psav->DDCPort = 0xAA; + psav->I2CPort = 0xA0; + break; + + case S3_SAVAGE4: + case S3_PROSAVAGE: + case S3_TWISTER: + case S3_PROSAVAGEDDR: + psav->DDCPort = 0xB1; + psav->I2CPort = 0xA0; + break; + } + + if (!SavageDDC1(pScrn->scrnIndex)) { + /* DDC1 failed,switch to DDC2 */ + if (xf86LoadSubModule(pScrn, "i2c")) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + if (SavageI2CInit(pScrn)) { + unsigned char tmp; + + InI2CREG(tmp,psav->DDCPort); + OutI2CREG(tmp | 0x13,psav->DDCPort); + xf86SetDDCproperties(pScrn,xf86PrintEDID( + xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C))); + OutI2CREG(tmp,psav->DDCPort); + } + } + } + } +} + +static void SavageGetPanelInfo(ScrnInfoPtr pScrn) +{ + SavagePtr psav= SAVPTR(pScrn); + vgaHWPtr hwp; + unsigned char cr6b; + int panelX, panelY; + char * sTechnology = "Unknown"; + enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */ + ActiveCRT = 0x01, + ActiveLCD = 0x02, + ActiveTV = 0x04, + ActiveCRT2 = 0x20, + ActiveDUO = 0x80 + }; + + hwp = VGAHWPTR(pScrn); + + /* Check LCD panel information */ + + cr6b = hwp->readCrtc( hwp, 0x6b ); + + panelX = (hwp->readSeq(hwp, 0x61) + + ((hwp->readSeq(hwp, 0x66) & 0x02) << 7) + 1) * 8; + panelY = hwp->readSeq(hwp, 0x69) + + ((hwp->readSeq(hwp, 0x6e) & 0x70) << 4) + 1; + + + /* OK, I admit it. I don't know how to limit the max dot clock + * for LCD panels of various sizes. I thought I copied the formula + * from the BIOS, but many users have informed me of my folly. + * + * Instead, I'll abandon any attempt to automatically limit the + * clock, and add an LCDClock option to XF86Config. Some day, + * I should come back to this. + */ + + + if( (hwp->readSeq( hwp, 0x39 ) & 0x03) == 0 ) + { + sTechnology = "TFT"; + } + else if( (hwp->readSeq( hwp, 0x30 ) & 0x01) == 0 ) + { + sTechnology = "DSTN"; + } + else + { + sTechnology = "STN"; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%dx%d %s LCD panel detected %s\n", + panelX, panelY, sTechnology, + cr6b & ActiveLCD ? "and active" : "but not active"); + + if( cr6b & ActiveLCD ) { + /* If the LCD is active and panel expansion is enabled, */ + /* we probably want to kill the HW cursor. */ + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "- Limiting video mode to %dx%d\n", + panelX, panelY ); + + psav->PanelX = panelX; + psav->PanelY = panelY; + + if( psav->LCDClock > 0.0 ) + { + psav->maxClock = psav->LCDClock * 1000.0; + xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, + "- Limiting dot clock to %1.2f MHz\n", + psav->LCDClock ); + } + } else { + psav->DisplayType = MT_CRT; + } +} + + static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) { EntityInfoPtr pEnt; @@ -786,7 +962,7 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) int mclk; vgaHWPtr hwp; int vgaCRIndex, vgaCRReg; - pointer ddc; + Bool dvi; TRACE(("SavagePreInit(%d)\n", flags)); @@ -1009,7 +1185,6 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) /*psav->agpMode = SAVAGE_MAX_AGP_MODE;*/ psav->agpSize = 16; - /* temporatly remove by Jiayo */ if (xf86GetOptValInteger(psav->Options, OPTION_AGP_MODE, &(psav->agpMode))) { if (psav->agpMode < 1) { @@ -1115,17 +1290,16 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: %s Tile Mode and Program it \n",(psav->bDisableTile?"Disable":"Enable")); } + #ifdef XF86DRI - psav->bDisableXvMC = FALSE; /* if you want to free up more mem for DRI,etc. */ + /* disabled by default...doesn't seem to work */ + psav->bDisableXvMC = TRUE; /* if you want to free up more mem for DRI,etc. */ if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_XVMC, &psav->bDisableXvMC)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: %s Hardware XvMC support\n",(psav->bDisableXvMC?"Disable":"Enable")); } - if (S3_SAVAGE3D_SERIES(psav->Chipset)) { - psav->bDisableXvMC = TRUE; /* no xvmc on old savages */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No Hardware XvMC support on Savage3D based chips.\n"); - } #endif + psav->disableCOB = FALSE; /* if you are having problems on savage4+ */ if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_COB, &psav->disableCOB)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, @@ -1141,6 +1315,11 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: %s use of the BCI for Xv\n",(psav->BCIforXv?"Enable":"Disable")); } + psav->dvi = FALSE; + if (xf86GetOptValBool(psav->Options, OPTION_DVI, &psav->dvi)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "%s DVI port support (Savage4 only)\n",(psav->dvi?"Force":"Disable")); + } /* Add more options here. */ @@ -1205,6 +1384,48 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) xfree(pEnt); + psav = SAVPTR(pScrn); + psav->IsSecondary = FALSE; + psav->IsPrimary = FALSE; + psav->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); + + if (xf86IsEntityShared(psav->pEnt->index)) { + if (xf86IsPrimInitDone(psav->pEnt->index)) { + + SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); + + psav->IsSecondary = TRUE; + pSavageEnt->pSecondaryScrn = pScrn; + psav->TvOn = pSavageEnt->TvOn; + } else { + SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); + + xf86SetPrimInitDone(psav->pEnt->index); + + psav->IsPrimary = TRUE; + pSavageEnt->pPrimaryScrn = pScrn; + pSavageEnt->TvOn = psav->TvOn; + } + } + + switch(psav->Chipset) { + case S3_SAVAGE_MX: + case S3_SUPERSAVAGE: + psav->HasCRTC2 = TRUE; + break; + default: + psav->HasCRTC2 = FALSE; + } + + /* until I figure out why cursor2 doesn't work, disable it for crtc2. -- AGD */ + if (psav->IsSecondary) { + psav->hwcursor = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HWCursor currently disabled for crtc2.\n"); + } + + if ((psav->IsSecondary || psav->IsPrimary) && !psav->UseBIOS) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BIOS currently required for Dualhead mode setting.\n"); + /* maybe throw in some more sanity checks here */ xf86DrvMsg(pScrn->scrnIndex, from, "Engine: \"%s\"\n", pScrn->chipset); @@ -1367,7 +1588,7 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) /* We use 128kB for the COB on all other chips. */ psav->cobSize = 0x20000; if (S3_SAVAGE3D_SERIES(psav->Chipset)) { - psav->cobIndex = 7; /* rev.A savage4 also uses 7 */ + psav->cobIndex = 7; /* rev.A savage4 apparently also uses 7 */ } else { psav->cobIndex = 2; } @@ -1380,6 +1601,25 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) psav->CursorKByte = (psav->cobOffset >> 10) - 4; psav->endfb = (psav->CursorKByte << 10) - 1; + if (psav->IsPrimary) { + pScrn->videoRam /= 2; + psav->videoRambytes = pScrn->videoRam * 1024; + psav->CursorKByte = (psav->videoRambytes >> 10) - 4; + psav->endfb = (psav->CursorKByte << 10) - 1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for primary head\n", + pScrn->videoRam); + } + + if(psav->IsSecondary) + { + pScrn->videoRam /= 2; + psav->videoRambytes = pScrn->videoRam * 1024; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for secondary head\n", + pScrn->videoRam); + } + /* reset graphics engine to avoid memory corruption */ VGAOUT8(vgaCRIndex, 0x66); cr66 = VGAIN8(vgaCRReg); @@ -1417,48 +1657,34 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) break; } - /* Do the DDC dance. */ /* S3/VIA's DDC code */ - ddc = xf86LoadSubModule(pScrn, "ddc"); - if (ddc) { - xf86LoaderReqSymLists(ddcSymbols, NULL); - switch( psav->Chipset ) { - case S3_SAVAGE3D: - case S3_SAVAGE_MX: - case S3_SUPERSAVAGE: - psav->DDCPort = 0xAA; - psav->I2CPort = 0xA0; - break; - - case S3_SAVAGE4: - case S3_PROSAVAGE: - case S3_TWISTER: - case S3_PROSAVAGEDDR: - psav->DDCPort = 0xB1; - psav->I2CPort = 0xA0; - break; - - case S3_SAVAGE2000: - psav->DDCPort = 0xAA; - psav->I2CPort = 0xA0; - break; - } + /* check for DVI/flat panel */ + dvi = FALSE; + if (psav->Chipset == S3_SAVAGE4) { + unsigned char sr30 = 0x00; + VGAOUT8(0x3c4, 0x30); + /* clear bit 1 */ + VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x02); + sr30 = VGAIN8(0x3c5); + if (sr30 & 0x02 /*0x04 */) { + dvi = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Digital Flat Panel Detected\n"); + } + } - if (!SavageDDC1(pScrn->scrnIndex)) { - /* DDC1 failed,switch to DDC2 */ - if (xf86LoadSubModule(pScrn, "i2c")) { - xf86LoaderReqSymLists(i2cSymbols,NULL); - if (SavageI2CInit(pScrn)) { - unsigned char tmp; - - InI2CREG(tmp,psav->DDCPort); - OutI2CREG(tmp | 0x13,psav->DDCPort); - xf86SetDDCproperties(pScrn,xf86PrintEDID( - xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C))); - OutI2CREG(tmp,psav->DDCPort); - } - } - } + if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || + S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) { + psav->DisplayType = MT_LCD; + } else if (dvi || ((psav->Chipset == S3_SAVAGE4) && psav->dvi)) { + psav->DisplayType = MT_DFP; + } else { + psav->DisplayType = MT_CRT; } + + if (psav->IsSecondary) + psav->DisplayType = MT_CRT; + + /* Do the DDC dance. */ + SavageDoDDC(pScrn); /* Savage ramdac speeds */ pScrn->numClocks = 4; @@ -1507,72 +1733,9 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) /* Check LCD panel information */ - if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || - S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) + if(psav->DisplayType == MT_LCD) { - unsigned char cr6b = hwp->readCrtc( hwp, 0x6b ); - - int panelX = (hwp->readSeq(hwp, 0x61) + - ((hwp->readSeq(hwp, 0x66) & 0x02) << 7) + 1) * 8; - int panelY = hwp->readSeq(hwp, 0x69) + - ((hwp->readSeq(hwp, 0x6e) & 0x70) << 4) + 1; - - char * sTechnology = "Unknown"; - - /* OK, I admit it. I don't know how to limit the max dot clock - * for LCD panels of various sizes. I thought I copied the formula - * from the BIOS, but many users have informed me of my folly. - * - * Instead, I'll abandon any attempt to automatically limit the - * clock, and add an LCDClock option to XF86Config. Some day, - * I should come back to this. - */ - - enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */ - ActiveCRT = 0x01, - ActiveLCD = 0x02, - ActiveTV = 0x04, - ActiveCRT2 = 0x20, - ActiveDUO = 0x80 - }; - - if( (hwp->readSeq( hwp, 0x39 ) & 0x03) == 0 ) - { - sTechnology = "TFT"; - } - else if( (hwp->readSeq( hwp, 0x30 ) & 0x01) == 0 ) - { - sTechnology = "DSTN"; - } - else - { - sTechnology = "STN"; - } - - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "%dx%d %s LCD panel detected %s\n", - panelX, panelY, sTechnology, - cr6b & ActiveLCD ? "and active" : "but not active"); - - if( cr6b & ActiveLCD ) { - /* If the LCD is active and panel expansion is enabled, */ - /* we probably want to kill the HW cursor. */ - - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "- Limiting video mode to %dx%d\n", - panelX, panelY ); - - psav->PanelX = panelX; - psav->PanelY = panelY; - - if( psav->LCDClock > 0.0 ) - { - psav->maxClock = psav->LCDClock * 1000.0; - xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, - "- Limiting dot clock to %1.2f MHz\n", - psav->LCDClock ); - } - } + SavageGetPanelInfo(pScrn); } #if 0 @@ -1587,41 +1750,6 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) } #endif - clockRanges = xnfalloc(sizeof(ClockRange)); - clockRanges->next = NULL; - clockRanges->minClock = psav->minClock; - clockRanges->maxClock = psav->maxClock; - clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = TRUE; - clockRanges->doubleScanAllowed = TRUE; - clockRanges->ClockDivFactor = 1.0; - clockRanges->ClockMulFactor = 1.0; - - i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, clockRanges, NULL, - 256, 2048, 16 * pScrn->bitsPerPixel, - 128, 2048, - pScrn->virtualX, pScrn->virtualY, - psav->videoRambytes, LOOKUP_BEST_REFRESH); - - if (i == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n"); - SavageFreeRec(pScrn); - vbeFree(psav->pVbe); - psav->pVbe = NULL; - return FALSE; - } - - xf86PruneDriverModes(pScrn); - - if (i == 0 || pScrn->modes == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - SavageFreeRec(pScrn); - vbeFree(psav->pVbe); - psav->pVbe = NULL; - return FALSE; - } - if( psav->UseBIOS ) { /* Go probe the BIOS for all the modes and refreshes at this depth. */ @@ -1664,6 +1792,41 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) } } + clockRanges = xnfalloc(sizeof(ClockRange)); + clockRanges->next = NULL; + clockRanges->minClock = psav->minClock; + clockRanges->maxClock = psav->maxClock; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = TRUE; + clockRanges->ClockDivFactor = 1.0; + clockRanges->ClockMulFactor = 1.0; + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, NULL, + 256, 4096, 16 * pScrn->bitsPerPixel, + 128, 4096, + pScrn->virtualX, pScrn->virtualY, + psav->videoRambytes, LOOKUP_BEST_REFRESH); + + if (i == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n"); + SavageFreeRec(pScrn); + vbeFree(psav->pVbe); + psav->pVbe = NULL; + return FALSE; + } + + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + SavageFreeRec(pScrn); + vbeFree(psav->pVbe); + psav->pVbe = NULL; + return FALSE; + } + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); pScrn->currentMode = pScrn->modes; xf86PrintModes(pScrn); @@ -1735,8 +1898,8 @@ static Bool SavageEnterVT(int scrnIndex, int flags) psav->LockHeld = 0; } #endif - - SavageSave(pScrn); + if (!psav->IsSecondary) + SavageSave(pScrn); if(SavageModeInit(pScrn, pScrn->currentMode)) { /* some BIOSes seem to enable HW cursor on PM resume */ if (!SAVPTR(pScrn)->hwc_on) @@ -1912,7 +2075,7 @@ static void SavageSave(ScrnInfoPtr pScrn) VGAOUT8(0x3c4, 0x1b); save->SR1B = VGAIN8(0x3c5); - /* Save flat panel expansion regsters. */ + /* Save flat panel expansion registers. */ if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { @@ -1980,6 +2143,13 @@ static void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, } #endif + if (psav->IsSecondary) { + /* Set up the mode. Don't clear video RAM. */ + SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); + SavageSetGBD(pScrn); + return; + } + if( Entering && (!S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || (psav->ForceInit)) ) @@ -2226,7 +2396,7 @@ static void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, VGAOUT8(0x3c4, 0x15); VGAOUT8(0x3c5, restore->SR15); - /* Restore flat panel expansion regsters. */ + /* Restore flat panel expansion registers. */ if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { int i; @@ -2489,7 +2659,10 @@ static Bool SavageMapFB(ScrnInfoPtr pScrn) "Internal error: could not map framebuffer\n"); return FALSE; } - psav->FBStart = psav->FBBase; + if (psav->IsSecondary) + psav->FBStart = psav->FBBase + 0x1000000; + else + psav->FBStart = psav->FBBase; } if (psav->Chipset == S3_SUPERSAVAGE) @@ -2497,10 +2670,22 @@ static Bool SavageMapFB(ScrnInfoPtr pScrn) psav->ApertureBase = psav->PciInfo->memBase[2]; else psav->ApertureBase = psav->FrameBufferBase + 0x02000000; - - psav->ApertureMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + + if (psav->IsSecondary) { + psav->ApertureMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + psav->PciTag, psav->ApertureBase, + 0x01000000 * 2); + psav->ApertureMap += 0x1000000; + } else if (psav->IsPrimary) { + psav->ApertureMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + psav->PciTag, psav->ApertureBase, + 0x01000000 * 2); + } else { + psav->ApertureMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, psav->PciTag, psav->ApertureBase, 0x01000000 * 5); + } + if (!psav->ApertureMap) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map aperture\n"); @@ -2513,8 +2698,12 @@ static Bool SavageMapFB(ScrnInfoPtr pScrn) } - pScrn->memPhysBase = psav->PciInfo->memBase[0]; - pScrn->fbOffset = 0; + if (psav->IsSecondary) + pScrn->fbOffset = pScrn->videoRam * 1024; + else + pScrn->fbOffset = 0; + + pScrn->memPhysBase = psav->PciInfo->memBase[0] + pScrn->fbOffset; return TRUE; } @@ -2589,9 +2778,8 @@ static Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Sufficient Videoram available for 3D\n"); return TRUE; } else { - xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D\n"); - xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Try a lower color depth or smaller desktop.\n"); - xf86DrvMsg(pScrn->scrnIndex,X_ERROR, + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D -- " + "Try a lower color depth or smaller desktop. " "For integrated savages try increasing the videoram in the BIOS.\n"); return FALSE; } @@ -2664,7 +2852,16 @@ static Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, return FALSE; #ifdef XF86DRI - if (((psav->Chipset == S3_TWISTER) + if (psav->IsSecondary) { + psav->directRenderingEnabled = FALSE; + } else if (xf86IsEntityShared(psav->pEnt->index)) { + /* Xinerama has sync problem with DRI, disable it for now */ + psav->directRenderingEnabled = FALSE; + xf86DrvMsg(scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with " + "DRI at present.\n"); + } else if (((psav->Chipset == S3_TWISTER) || (psav->Chipset == S3_PROSAVAGE) || (psav->Chipset == S3_SAVAGE4) || (psav->Chipset == S3_SAVAGE_MX) @@ -2853,8 +3050,13 @@ static Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, #endif #ifdef XvExtension - if( !psav->FBStart2nd && !psav->NoAccel && !SavagePanningCheck(pScrn) ) - SavageInitVideo( pScreen ); + if( !psav->FBStart2nd && !psav->NoAccel /*&& !SavagePanningCheck(pScrn)*/ ) { + if (psav->IsSecondary) + /* Xv should work on crtc2, but I haven't gotten there yet. -- AGD */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv currently disabled for crtc2.\n"); + else + SavageInitVideo( pScreen ); + } #endif #ifdef XF86DRI @@ -2908,12 +3110,7 @@ static int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen) } if (!psav->FBStart2nd) { -#if 0 - ret = fbScreenInit(pScreen, FBStart, width, height, - pScrn->xDpi, pScrn->yDpi, - displayWidth, - pScrn->bitsPerPixel); -#endif + ret = fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi, pScrn->yDpi, psav->ulAperturePitch / (pScrn->bitsPerPixel >> 3), /*displayWidth,*/ @@ -2955,6 +3152,7 @@ static ModeStatus SavageValidMode(int index, DisplayModePtr pMode, { ScrnInfoPtr pScrn = xf86Screens[index]; SavagePtr psav = SAVPTR(pScrn); + int refresh; TRACE(("SavageValidMode\n")); @@ -2970,16 +3168,19 @@ static ModeStatus SavageValidMode(int index, DisplayModePtr pMode, return MODE_VIRTUAL_Y; } - if( - !psav->CrtOnly && - psav->PanelX && - ( - (pMode->HDisplay > psav->PanelX) || - (pMode->VDisplay > psav->PanelY) - ) - ) + + if((psav->DisplayType == MT_LCD) && + ((pMode->HDisplay > psav->PanelX) || + (pMode->VDisplay > psav->PanelY))) return MODE_PANEL; + if (psav->UseBIOS) { + refresh = (pMode->Clock * 1000) / (pMode->HTotal * pMode->VTotal); + return (SavageMatchBiosMode(pScrn,pMode->HDisplay, + pMode->VDisplay, + refresh,NULL,NULL)); + } + return MODE_OK; } @@ -2993,6 +3194,8 @@ static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) SavageRegPtr new = &psav->ModeReg; vgaRegPtr vganew = &hwp->ModeReg; int vgaCRIndex, vgaCRReg, vgaIOBase; + int refresh; + unsigned int newmode=0, newrefresh=0; vgaIOBase = hwp->IOBase; vgaCRIndex = vgaIOBase + 4; @@ -3020,6 +3223,24 @@ static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) mode->CrtcVTotal); #endif + if (psav->IsSecondary) { + refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); + + SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, + &newmode,&newrefresh); + new->mode = newmode; + new->refresh = newrefresh; + + /* do it! */ + SavageWriteMode(pScrn, vganew, new, TRUE); + SavageStreamsOn(pScrn); + + if (psav->FBStart2nd) + SavageInitSecondaryStream(pScrn); + + SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; + } if (pScrn->bitsPerPixel == 8) @@ -3085,63 +3306,14 @@ static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) if( psav->UseBIOS ) { int refresh; - SavageModeEntryPtr pmt; - - /* Scan through our BIOS list to locate the closest valid mode. */ - - /* If we ever break 4GHz clocks on video boards, we'll need to - * change this. - */ + unsigned int newmode=0, newrefresh=0; refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); -#ifdef EXTENDED_DEBUG - ErrorF( "Desired refresh rate = %dHz\n", refresh ); -#endif - - for( i = 0, pmt = psav->ModeTable->Modes; - i < psav->ModeTable->NumModes; - i++, pmt++ ) - { - if( (pmt->Width == mode->HDisplay) && - (pmt->Height == mode->VDisplay) ) - { - int jDelta = 99; - int jBest = 0; - - /* We have an acceptable mode. Find a refresh rate. */ - - new->mode = pmt->VesaMode; - for( j = 0; j < pmt->RefreshCount; j++ ) - { - if( pmt->RefreshRate[j] == refresh ) - { - /* Exact match. */ - jBest = j; - break; - } - else if( iabs(pmt->RefreshRate[j] - refresh) < jDelta ) - { - jDelta = iabs(pmt->RefreshRate[j] - refresh); - jBest = j; - } - } - - new->refresh = pmt->RefreshRate[jBest]; - break; - } - } - - if( new->mode ) { - /* Success: we found a match in the BIOS. */ - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Chose mode %x at %dHz.\n", new->mode, new->refresh ); - } - else { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "No suitable BIOS mode found for %dx%d %dMHz.\n", - mode->HDisplay, mode->VDisplay, mode->Clock/1000 ); - } + SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, + &newmode,&newrefresh); + new->mode = newmode; + new->refresh = newrefresh; } if( !new->mode ) { @@ -3397,10 +3569,22 @@ static Bool SavageSaveScreen(ScreenPtr pScreen, int mode) return vgaHWSaveScreen(pScreen, mode); } +void SavageAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SavagePtr psav = SAVPTR(pScrn); + + if (psav->IsSecondary) { + SavageDoAdjustFrame(pScrn, x, y, TRUE); + } else { + SavageDoAdjustFrame(pScrn, x, y, FALSE); + } + +} + void -SavageAdjustFrame(int scrnIndex, int x, int y, int flags) +SavageDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int crtc2) { - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; SavagePtr psav = SAVPTR(pScrn); DisplayModePtr currentMode = pScrn->currentMode; int address=0,top=0,left=0; @@ -3423,62 +3607,66 @@ SavageAdjustFrame(int scrnIndex, int x, int y, int flags) } } + address += pScrn->fbOffset; + /* * because we align the viewport to the width and height of one tile - * we shoud update the locate of frame + * we should update the locate of frame */ pScrn->frameX0 = left; pScrn->frameY0 = top; pScrn->frameX1 = left + currentMode->HDisplay - 1; - pScrn->frameY1 = top+ currentMode->VDisplay - 1; - - if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset)) { - OUTREG32(PRI_STREAM_FBUF_ADDR0,address | 0xFFFFFFFC); /* IGA1 */ - OUTREG32(PRI_STREAM_FBUF_ADDR1,address | 0x80000000); - OUTREG32(PRI_STREAM2_FBUF_ADDR0,address | 0xFFFFFFFC); /* IGA2 */ - OUTREG32(PRI_STREAM2_FBUF_ADDR1,address | 0x80000000); + pScrn->frameY1 = top + currentMode->VDisplay - 1; + + if (psav->Chipset == S3_SAVAGE_MX) { + if (!crtc2) { + OUTREG32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); + OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC);/* IGA1 */ + } else { + OUTREG32(PRI_STREAM2_FBUF_ADDR0, address & 0xFFFFFFFC);/* IGA2 */ + OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFFC); + } + } else if (psav->Chipset == S3_SUPERSAVAGE) { + if (!crtc2) { + /* IGA1 */ + OUTREG32(PRI_STREAM_FBUF_ADDR0, 0x80000000); + OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); + } else { + /* IGA2 */ + OUTREG32(PRI_STREAM2_FBUF_ADDR0, ((address & 0xFFFFFFF8) | 0x80000000)); + OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFF8); + } } else { - OUTREG32(PSTREAM_FBADDR0_REG,address | 0xFFFFFFFC); - OUTREG32(PSTREAM_FBADDR1_REG,address | 0x80000000); + OUTREG32(PRI_STREAM_FBUF_ADDR0,address | 0xFFFFFFFC); + OUTREG32(PRI_STREAM_FBUF_ADDR1,address | 0x80000000); } - + return; } -#if 0 -void SavageAdjustFrame(int scrnIndex, int x, int y, int flags) +Bool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - vgaHWPtr hwp = VGAHWPTR(pScrn); + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; SavagePtr psav = SAVPTR(pScrn); - int Base; - int vgaCRIndex, vgaCRReg, vgaIOBase; - vgaIOBase = hwp->IOBase; - vgaCRIndex = vgaIOBase + 4; - vgaCRReg = vgaIOBase + 5; + Bool success; - TRACE(("SavageAdjustFrame(%d,%d,%x)\n", x, y, flags)); + TRACE(("SavageSwitchMode\n")); - if (psav->ShowCache && y) - y += pScrn->virtualY - 1; + SavageStreamsOff(xf86Screens[scrnIndex]); - Base = ((y * pScrn->displayWidth + (x&~1)) * - (psav->primStreamBpp / 8)) >> 2; - /* now program the start address registers */ - VGAOUT16(vgaCRIndex, (Base & 0x00ff00) | 0x0c); - VGAOUT16(vgaCRIndex, ((Base & 0x00ff) << 8) | 0x0d); - VGAOUT8(vgaCRIndex, 0x69); - VGAOUT8(vgaCRReg, (Base & 0x7f0000) >> 16); + success = SavageModeInit(xf86Screens[scrnIndex], mode); - return; -} -#endif + /* switching mode on primary will reset secondary. it needs to be reset as well*/ + if (psav->IsPrimary) { + DevUnion* pPriv; + SavageEntPtr pSavEnt; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gSavageEntityIndex); + pSavEnt = pPriv->ptr; + SavageModeInit(pSavEnt->pSecondaryScrn, pSavEnt->pSecondaryScrn->currentMode); + } -Bool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) -{ - TRACE(("SavageSwitchMode\n")); - SavageStreamsOff(xf86Screens[scrnIndex]); - return SavageModeInit(xf86Screens[scrnIndex], mode); + return success; } @@ -3795,7 +3983,6 @@ SavagePrintRegs(ScrnInfoPtr pScrn) ErrorF("\n\n"); } - static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) { SavagePtr psav = SAVPTR(pScrn); @@ -3803,35 +3990,40 @@ static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) TRACE(("SavageDPMS(%d,%x)\n", mode, flags)); - VGAOUT8(0x3c4, 0x08); - sr8 = VGAIN8(0x3c5); - sr8 |= 0x06; - VGAOUT8(0x3c5, sr8); - - VGAOUT8(0x3c4, 0x0d); - srd = VGAIN8(0x3c5); - - srd &= 0x03; + if (psav->DisplayType == MT_CRT) { + VGAOUT8(0x3c4, 0x08); + sr8 = VGAIN8(0x3c5); + sr8 |= 0x06; + VGAOUT8(0x3c5, sr8); + + VGAOUT8(0x3c4, 0x0d); + srd = VGAIN8(0x3c5); + + srd &= 0x03; + + switch (mode) { + case DPMSModeOn: + break; + case DPMSModeStandby: + srd |= 0x10; + break; + case DPMSModeSuspend: + srd |= 0x40; + break; + case DPMSModeOff: + srd |= 0x50; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); + break; + } - switch (mode) { - case DPMSModeOn: - break; - case DPMSModeStandby: - srd |= 0x10; - break; - case DPMSModeSuspend: - srd |= 0x40; - break; - case DPMSModeOff: - srd |= 0x50; - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); - break; + VGAOUT8(0x3c4, 0x0d); + VGAOUT8(0x3c5, srd); } - - if ((!psav->CrtOnly) && psav->PanelX) { - if (S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { + + if (psav->DisplayType == MT_LCD || psav->DisplayType == MT_DFP) { + if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) && psav->UseBIOS) { SavageSetPanelEnabled(psav, (mode == DPMSModeOn)); } else { switch (mode) { @@ -3852,9 +4044,6 @@ static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) } } - VGAOUT8(0x3c4, 0x0d); - VGAOUT8(0x3c5, srd); - return; } diff --git a/src/savage_driver.h b/src/savage_driver.h index 9d535d6..1b1cda4 100644 --- a/src/savage_driver.h +++ b/src/savage_driver.h @@ -35,6 +35,22 @@ #include "GL/glxint.h" #endif +typedef enum { + MT_NONE, + MT_CRT, + MT_LCD, + MT_DFP, + MT_TV +} SavageMonitorType; + +typedef struct +{ + Bool HasSecondary; + Bool TvOn; + ScrnInfoPtr pSecondaryScrn; + ScrnInfoPtr pPrimaryScrn; + +} SavageEntRec, *SavageEntPtr; #ifndef uint typedef unsigned int uint; @@ -362,6 +378,16 @@ typedef struct _Savage { StatInfoRec StatInfo; /* save the SVGA state */ + /* for dvi option */ + Bool dvi; + + SavageMonitorType DisplayType; + /* DuoView stuff */ + Bool HasCRTC2; /* MX, IX, Supersavage */ + Bool IsSecondary; /* second Screen */ + Bool IsPrimary; /* first Screen */ + EntityInfoPtr pEnt; + } SavageRec, *SavagePtr; /* Video flags. */ @@ -420,6 +446,7 @@ extern void SavageCommonCalcClock(long freq, int min_m, int min_n1, long freq_min, long freq_max, unsigned char *mdiv, unsigned char *ndiv); void SavageAdjustFrame(int scrnIndex, int y, int x, int flags); +void SavageDoAdjustFrame(ScrnInfoPtr pScrn, int y, int x, int crtc2); Bool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); /* In savage_cursor.c. */ @@ -456,6 +483,8 @@ void SavageSetVESAMode( SavagePtr psav, int n, int Refresh ); void SavageSetPanelEnabled( SavagePtr psav, Bool active ); void SavageFreeBIOSModeTable( SavagePtr psav, SavageModeTablePtr* ppTable ); SavageModeTablePtr SavageGetBIOSModeTable( SavagePtr psav, int iDepth ); +ModeStatus SavageMatchBiosMode(ScrnInfoPtr pScrn,int width,int height,int refresh,
+ unsigned int *vesaMode,unsigned int *newRefresh); unsigned short SavageGetBIOSModes( SavagePtr psav, diff --git a/src/savage_regs.h b/src/savage_regs.h index 9d80e94..4a6cb99 100644 --- a/src/savage_regs.h +++ b/src/savage_regs.h @@ -159,9 +159,21 @@ enum S3CHIPTAGS { #define S3_SEC_BD_LOW 0X8178 #define S3_SEC_BD_HIGH 0X817c +/* duoview */ + #define SELECT_IGA1 0x4026 #define SELECT_IGA2_READS_WRITES 0x4f26 +#define SelectIGA1() \ +do { \ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1); \ +} while (0) + +#define SelectIGA2() \ +do { \ + OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES); \ +} while (0) + #define MEM_PS1 0x10 /*CRCA_4 :Primary stream 1*/ #define MEM_PS2 0x20 /*CRCA_5 :Primary stream 2*/ #define MEM_SS1 0x40 /*CRCA_6 :Secondary stream 1*/ diff --git a/src/savage_streams.c b/src/savage_streams.c index fa11c40..b1c5ab2 100644 --- a/src/savage_streams.c +++ b/src/savage_streams.c @@ -130,27 +130,6 @@ void SavageInitStreamsOld(ScrnInfoPtr pScrn) xf86ErrorFVerb(STREAMS_TRACE, "SavageInitStreams\n" ); - /* Primary stream reflects the frame buffer. */ - - if (!psav->bTiled) { - OUTREG(PSTREAM_STRIDE_REG, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) | - (psav->lDelta & 0x00001fff)); - } - else if (pScrn->bitsPerPixel == 16) { - /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */ - OUTREG(PSTREAM_STRIDE_REG, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) - | 0x80000000 | (psav->lDelta & 0x00001fff)); - } - else if (pScrn->bitsPerPixel == 32) { - OUTREG(PSTREAM_STRIDE_REG, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) - | 0xC0000000 | (psav->lDelta & 0x00001fff)); - } - OUTREG(PSTREAM_FBSIZE_REG, - pScrn->virtualY * pScrn->virtualX * (pScrn->bitsPerPixel >> 3)); - if (psav->FBStart2nd) { unsigned long jDelta = pScrn->displayWidth; @@ -165,6 +144,8 @@ void SavageInitStreamsOld(ScrnInfoPtr pScrn) case 16: format = 5 << 24; break; case 24: format = 7 << 24; break; } + OUTREG(PSTREAM_FBSIZE_REG, + pScrn->virtualY * pScrn->virtualX * (pScrn->bitsPerPixel >> 3)); } OUTREG( PSTREAM_WINDOW_START_REG, OS_XY(0,0) ); @@ -225,34 +206,28 @@ SavageInitStreamsNew(ScrnInfoPtr pScrn) xf86ErrorFVerb(STREAMS_TRACE, "SavageInitStreams\n" ); - if( - S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && + if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && + (psav->DisplayType == MT_LCD) && !psav->CrtOnly && - !psav->TvOn - ) { + !psav->TvOn ) + { OverlayParamInit( pScrn ); } - /* Primary stream reflects the frame buffer. */ - OUTREG32(PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset); - if (!psav->bTiled) { - OUTREG(PRI_STREAM_STRIDE, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) | - (psav->lDelta & 0x00001fff)); - } - else if (pScrn->bitsPerPixel == 16) { - /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */ - OUTREG(PRI_STREAM_STRIDE, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) - | 0x80000000 | (psav->lDelta & 0x00001fff)); - } - else if (pScrn->bitsPerPixel == 32) { - OUTREG(PRI_STREAM_STRIDE, - (((psav->lDelta * 2) << 16) & 0x3FFFE000) - | 0xC0000000 | (psav->lDelta & 0x00001fff)); - } - OUTREG(PRI_STREAM_BUFFERSIZE, + if (psav->IsSecondary) { + OUTREG(PRI_STREAM2_BUFFERSIZE, + pScrn->virtualX * pScrn->virtualY * (pScrn->bitsPerPixel >> 3)); + } else if (psav->IsPrimary){ + OUTREG(PRI_STREAM_BUFFERSIZE, pScrn->virtualX * pScrn->virtualY * (pScrn->bitsPerPixel >> 3)); + } else { + OUTREG(PRI_STREAM_BUFFERSIZE, + pScrn->virtualX * pScrn->virtualY * (pScrn->bitsPerPixel >> 3)); +#if 0 + OUTREG(PRI_STREAM2_BUFFERSIZE, + pScrn->virtualX * pScrn->virtualY * (pScrn->bitsPerPixel >> 3)); +#endif + } if (psav->FBStart2nd) { unsigned long jDelta = pScrn->displayWidth; @@ -260,51 +235,88 @@ SavageInitStreamsNew(ScrnInfoPtr pScrn) OUTREG( PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset ); OUTREG( PRI_STREAM_STRIDE, jDelta ); } -#if 0 - else { - jDelta = pScrn->displayWidth * (pScrn->bitsPerPixel + 7) / 8; - } -#endif - /*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)); - } + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); + OUTREG( SEC_STREAM2_HSCALING, 0 ); + OUTREG( SEC_STREAM2_VSCALING, 0 ); + OUTREG( BLEND_CONTROL, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR0, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR1, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR2, 0 ); + OUTREG( SEC_STREAM2_WINDOW_START, 0 ); + OUTREG( SEC_STREAM2_WINDOW_SZ, 0 ); +/* OUTREG( SEC_STREAM2_BUFFERSIZE, 0 ); */ + OUTREG( SEC_STREAM2_OPAQUE_OVERLAY, 0 ); + OUTREG( SEC_STREAM2_STRIDE_LPB, 0 ); + + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM2_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, 0x01F1547E ); + } else if (psav->IsPrimary) { + 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 ); + } else { + 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 + sleep(1); + OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); + OUTREG( SEC_STREAM2_HSCALING, 0 ); + OUTREG( SEC_STREAM2_VSCALING, 0 ); + OUTREG( BLEND_CONTROL, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR0, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR1, 0 ); + OUTREG( SEC_STREAM2_FBUF_ADDR2, 0 ); + OUTREG( SEC_STREAM2_WINDOW_START, 0 ); + OUTREG( SEC_STREAM2_WINDOW_SZ, 0 ); +/* OUTREG( SEC_STREAM2_BUFFERSIZE, 0 ); */ + OUTREG( SEC_STREAM2_OPAQUE_OVERLAY, 0 ); + OUTREG( SEC_STREAM2_STRIDE_LPB, 0 ); + + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM2_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, 0x01F1547E ); #endif + } } /* @@ -477,18 +489,50 @@ SavageStreamsOn(ScrnInfoPtr pScrn) jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAM1; - /* Wait for VBLANK. */ - - VerticalRetraceWait(); - - /* Fire up streams! */ - - VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); - + if (psav->IsSecondary) { + SelectIGA2(); + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* Fire up streams! */ + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + SelectIGA1(); /* 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 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, 0x01F1547E ); + } else if (psav->IsPrimary) { + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* 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 { + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* Fire up streams! */ + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); +#if 0 + SelectIGA2(); + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* Fire up streams! */ + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + SelectIGA1(); +#endif + /* 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 + sleep(1); + OUTREG( SEC_STREAM2_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, 0x01F1547E ); +#endif + } } else { @@ -545,8 +589,20 @@ SavageStreamsOff(ScrnInfoPtr pScrn) VerticalRetraceWait(); /* Kill streams. */ - - VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + if (psav->IsSecondary) { + SelectIGA2(); + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + SelectIGA1(); + } else if (psav->IsPrimary) { + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + } else { + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); +#if 0 + SelectIGA2(); + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + SelectIGA1(); +#endif + } VGAOUT16( vgaCRIndex, 0x0093 ); VGAOUT8( vgaCRIndex, 0x92 ); diff --git a/src/savage_vbe.c b/src/savage_vbe.c index a796850..58f0bee 100644 --- a/src/savage_vbe.c +++ b/src/savage_vbe.c @@ -3,6 +3,8 @@ #include "savage_driver.h" #include "savage_vbe.h" +#define iabs(a) ((int)(a)>0?(a):(-(a))) + #if X_BYTE_ORDER == X_LITTLE_ENDIAN #define B_O16(x) (x) #define B_O32(x) (x) @@ -16,6 +18,8 @@ Bool vbeModeInit( vbeInfoPtr, int ); static int SavageGetDevice( SavagePtr psav ); /*static int SavageGetTVType( SavagePtr psav );*/ +void SavageSetVESAModeCrtc1( SavagePtr psav, int n, int Refresh ); +void SavageSetVESAModeCrtc2( SavagePtr psav, int n, int Refresh ); static void SavageClearVM86Regs( xf86Int10InfoPtr pInt ) @@ -49,6 +53,65 @@ SavageSetTextMode( SavagePtr psav ) xf86ExecX86int10( psav->pVbe->pInt10 ); } +void +SavageSetVESAModeCrtc1(SavagePtr psav, int n, int refresh) +{ + unsigned char byte; + + xf86Msg(X_INFO,"SavageSetVESAModeCrtc1:mode=0x%x,refresh=%dHZ\n",n,refresh); + + SavageClearVM86Regs(psav->pVbe->pInt10); + + /* set active displays. */ + psav->pVbe->pInt10->ax = S3_EXTBIOS_INFO; + psav->pVbe->pInt10->bx = S3_SET_ACTIVE_DISP; + if (psav->TvOn) + psav->pVbe->pInt10->cx = 0x87; /* lcd, tv, crt, duoview */ + else + psav->pVbe->pInt10->cx = 0x83; /* lcd, crt, duoview */ + xf86ExecX86int10(psav->pVbe->pInt10); + + SavageClearVM86Regs(psav->pVbe->pInt10); + + /* Establish the refresh rate for this mode. */ + psav->pVbe->pInt10->ax = S3_EXTBIOS_INFO; + psav->pVbe->pInt10->bx = S3_SET_REFRESH; + psav->pVbe->pInt10->cx = n & 0x1ff; + psav->pVbe->pInt10->di = refresh & 0xffff; + xf86ExecX86int10(psav->pVbe->pInt10); + + /* SR01:turn off screen */ + OUTREG8 (SEQ_ADDRESS_REG,0x01); + byte = INREG8(SEQ_DATA_REG) | 0x20; + OUTREG8(SEQ_DATA_REG,byte); + + psav->pVbe->pInt10->ax = BIOS_SET_VBE_MODE; + psav->pVbe->pInt10->bx = n; + xf86ExecX86int10(psav->pVbe->pInt10); + +} + +void +SavageSetVESAModeCrtc2( SavagePtr psav, int n, int refresh ) +{ + + xf86Msg(X_INFO,"SavageSetVESAModeCrtc2:mode=0x%x,refresh=%dHZ\n",n,refresh); + + SavageClearVM86Regs(psav->pVbe->pInt10); + + UnLockExtRegs(); + + psav->pVbe->pInt10->ax = S3_EXTBIOS_INFO; + psav->pVbe->pInt10->bx = S3_ALT_SET_ACTIVE_DISP; + if (psav->TvOn) + psav->pVbe->pInt10->cx = 0x87; /* lcd, tv, crt, duoview */ + else + psav->pVbe->pInt10->cx = 0x83; /* lcd, crt, duoview */ + psav->pVbe->pInt10->dx = n & 0x1ff; + psav->pVbe->pInt10->di = refresh & 0xffff; + xf86ExecX86int10(psav->pVbe->pInt10); + +} void SavageSetVESAMode( SavagePtr psav, int n, int Refresh ) @@ -56,6 +119,15 @@ SavageSetVESAMode( SavagePtr psav, int n, int Refresh ) int iDevInfo; static int iCount = 0; + if (psav->IsSecondary) { + SavageSetVESAModeCrtc2(psav, n, Refresh); + return; + } + if (psav->IsPrimary) { + SavageSetVESAModeCrtc1(psav, n, Refresh); + return; + } + /* Get current display device status. */ iDevInfo = SavageGetDevice(psav); @@ -318,3 +390,71 @@ SavageGetBIOSModes( return iModeCount; } + +ModeStatus SavageMatchBiosMode(ScrnInfoPtr pScrn,int width,int height,int refresh, + unsigned int *vesaMode,unsigned int *newRefresh) +{ + SavageModeEntryPtr pmt; + Bool found = FALSE; + SavagePtr psav = SAVPTR(pScrn); + int i,j; + unsigned int chosenVesaMode = 0; + unsigned int chosenRefresh = 0; + + /* Scan through our BIOS list to locate the closest valid mode. */ + + /* + * If we ever break 4GHz clocks on video boards, we'll need to + * change this. + * refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); + * now we use VRefresh directly,instead of by calculating from dot clock + */ + + for( i = 0, pmt = psav->ModeTable->Modes; + i < psav->ModeTable->NumModes; + i++, pmt++ ) + { + if( (pmt->Width == width) && + (pmt->Height == height) ) + { + int jDelta = 99; + int jBest = 0; + + /* We have an acceptable mode. Find a refresh rate. */ + chosenVesaMode = pmt->VesaMode; + if (vesaMode) + *vesaMode = chosenVesaMode; + for( j = 0; j < pmt->RefreshCount; j++ ) + { + if( pmt->RefreshRate[j] == refresh ) + { + /* Exact match. */ + jBest = j; + break; + } + else if( iabs(pmt->RefreshRate[j] - refresh) < jDelta ) + { + jDelta = iabs(pmt->RefreshRate[j] - refresh); + jBest = j; + } + } + chosenRefresh = pmt->RefreshRate[jBest]; + if (newRefresh) + *newRefresh = chosenRefresh; + found = TRUE; + break; + } + } + + if( found ) { + /* Success: we found a match in the BIOS. */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chose mode %x at %dHz.\n", chosenVesaMode, chosenRefresh ); + return MODE_OK; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "No suitable BIOS mode found for %dx%d %dHz.\n", + width, height, refresh); + return MODE_NOMODE; + } +} diff --git a/src/savage_vbe.h b/src/savage_vbe.h index ba77773..43d758d 100644 --- a/src/savage_vbe.h +++ b/src/savage_vbe.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/savage/savage_vbe.h,v 1.3 2002/05/14 20:19:52 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/savage/savage_vbe.h,v 1.1 2000/12/02 01:16:15 dawes Exp $ */ /* This file was originally part of the Linux Real-Mode Interface, or LRMI. @@ -16,6 +16,58 @@ This software has NO WARRANTY. Use it at your own risk. #ifndef _SAVAGEVBE_H #define _SAVAGEVBE_H +/* + * Common BIOS functions + */ + +#define BIOS_SET_VBE_MODE 0x4F02 +#define BIOS_GET_VBE_MODE 0x4F03 +#define BIOS_SVGA_STATE 0x4F04 +#define BIOS_LOG_SCANLINE 0x4F06 +#define BIOS_VBE_PM_SERVICE 0x4F10 +#define S3_EXTBIOS_INFO 0x4F14 /* S3 Extended BIOS services */ +#define BIOS_VBE_DDC 0x4F15 + +/************************************************************************* + * Defines for BIOS compliant with S3 (Mobile and Desktop) PCI Video + * Bios External Interface Specification, Core Revision 3.02+ + * + * e.g. used by Trio3D, GX-3 + *************************************************************************/ + +#define S3_GET_SVGA_BUF 0x0000 +#define S3_SAVE_SVGA_STATE 0x0001 +#define S3_RESTORE_SVGA_STATE 0x0002 +/* + * For S3_EXTBIOS_INFO (0x4F14) services + */ +#define S3_VBE_INFO 0x0000 /* fn0: Query S3/VBE info */ + +#define S3_SET_REFRESH 0x0001 /* fn1,sub0: Set Refresh Rate for Mode */ +#define S3_GET_REFRESH 0x0101 /* fn1,sub1: Get Refresh Rate for Mode */ +#define S3_QUERY_REFRESH 0x0201 /* fn1,sub2: Query Refresh Rates for Mode */ + +#define S3_QUERY_MODELIST 0x0202 /* fn2,sub2: Query Mode List */ +#define S3_GET_EXT_MODEINFO 0x0302 /* fn2,sub3: Get Extended Mode Info */ + +#define S3_QUERY_ATTACHED 0x0004 /* fn4,sub0: Query detected displays */ + +#define S3_GET_ACTIVE_DISP 0x0103 /* fn3,sub1: Get Active Display */ +#define S3_SET_ACTIVE_DISP 0x0003 /* fn3,sub0: Set Active Display */ +#define S3_ALT_SET_ACTIVE_DISP 0x8003 /* fn8003,sub0: Alternate Set Active Display */ + +#define S3_SET_TV_CONFIG 0x0007 /* fn7,sub0: Set TV Configuration */ +#define S3_GET_TV_CONFIG 0x0107 /* fn7,sub1: Get TV Configuration */ + + +#define BIOS_CRT1_ONLY 0x01 +#define BIOS_LCD_ONLY 0x02 +#define BIOS_TV_NTSC 0x04 +#define BIOS_TV_PAL 0x08 +#define BIOS_TV_ONLY 0x0c +#define BIOS_DVI_ONLY 0x20 +#define BIOS_DEVICE_MASK (BIOS_CRT1_ONLY|BIOS_LCD_ONLY|BIOS_TV_ONLY|BIOS_DVI_ONLY) + /* structures for vbe 2.0 */ #ifndef __GNUC__ diff --git a/src/savage_video.c b/src/savage_video.c index 848ae6b..9c03bb5 100644 --- a/src/savage_video.c +++ b/src/savage_video.c @@ -235,8 +235,16 @@ SavageClipVWindow(ScrnInfoPtr pScrn) if( (psav->Chipset == S3_SAVAGE_MX) || (psav->Chipset == S3_SUPERSAVAGE) || (psav->Chipset == S3_SAVAGE2000) ) { - OUTREG(SEC_STREAM_WINDOW_SZ, 0); - + if (psav->IsSecondary) { + OUTREG(SEC_STREAM2_WINDOW_SZ, 0); + } else if (psav->IsPrimary) { + OUTREG(SEC_STREAM_WINDOW_SZ, 0); + } else { + OUTREG(SEC_STREAM_WINDOW_SZ, 0); +#if 0 + OUTREG(SEC_STREAM2_WINDOW_SZ, 0); +#endif + } } else { OUTREG( SSTREAM_WINDOW_SIZE_REG, 1); OUTREG( SSTREAM_WINDOW_START_REG, 0x03ff03ff); @@ -252,10 +260,8 @@ void SavageInitVideo(ScreenPtr pScreen) int num_adaptors; xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n"); - if( - S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || - (psav->Chipset == S3_SAVAGE2000) - ) + if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || + (psav->Chipset == S3_SAVAGE2000)) { newAdaptor = SavageSetupImageVideo(pScreen); SavageInitOffscreenImages(pScreen); @@ -370,40 +376,137 @@ void SavageSetColorKeyNew(ScrnInfoPtr pScrn) blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; if( !pPriv->colorKey ) { - OUTREG( SEC_STREAM_CKEY_LOW, 0 ); - OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); - OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 ); + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); + } else { + OUTREG( SEC_STREAM_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); +#if 0 + sleep(1); + OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); + OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); +#endif + } } else { switch (pScrn->depth) { case 8: - OUTREG( SEC_STREAM_CKEY_LOW, - 0x47000000 | (pPriv->colorKey & 0xFF) ); - OUTREG( SEC_STREAM_CKEY_UPPER, - 0x47000000 | (pPriv->colorKey & 0xFF) ); + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + } else { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x47000000 | (pPriv->colorKey & 0xFF) ); +#if 0 + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x47000000 | (pPriv->colorKey & 0xFF) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x47000000 | (pPriv->colorKey & 0xFF) ); +#endif + } break; case 15: - OUTREG( SEC_STREAM_CKEY_LOW, - 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); - OUTREG( SEC_STREAM_CKEY_UPPER, - 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + } else { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); +#if 0 + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); +#endif + } break; case 16: - OUTREG( SEC_STREAM_CKEY_LOW, - 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); - OUTREG( SEC_STREAM_CKEY_UPPER, - 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); + } else { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); +#if 0 + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); +#endif + } break; case 24: - OUTREG( SEC_STREAM_CKEY_LOW, - 0x47000000 | (red<<16) | (green<<8) | (blue) ); - OUTREG( SEC_STREAM_CKEY_UPPER, - 0x47000000 | (red<<16) | (green<<8) | (blue) ); + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + } else { + OUTREG( SEC_STREAM_CKEY_LOW, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + OUTREG( SEC_STREAM_CKEY_UPPER, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); +#if 0 + OUTREG( SEC_STREAM2_CKEY_LOW, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); + OUTREG( SEC_STREAM2_CKEY_UPPER, + 0x47000000 | (red<<16) | (green<<8) | (blue) ); +#endif + } break; } /* We assume destination colorkey */ - OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 ); + if (psav->IsSecondary) { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); + } else if (psav->IsPrimary) { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); + } else { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); +#if 0 + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); +#endif + } } } @@ -453,7 +556,7 @@ void SavageSetColorNew( ScrnInfoPtr pScrn ) int k1, k2, k3, k4, k5, k6, k7, kb; double s = pPriv->saturation / 128.0; double h = pPriv->hue * 0.017453292; - unsigned long assembly; + unsigned long assembly1, assembly2, assembly3; xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n", pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue ); @@ -483,22 +586,39 @@ void SavageSetColorNew( ScrnInfoPtr pScrn ) k1 = (int)(dk1+0.5) & 0x1ff; k2 = (int)(dk2+0.5) & 0x1ff; k3 = (int)(dk3+0.5) & 0x1ff; - assembly = (k3<<18) | (k2<<9) | k1; - xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx ", assembly ); - OUTREG( SEC_STREAM_COLOR_CONVERT1, assembly ); + assembly1 = (k3<<18) | (k2<<9) | k1; + xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx ", assembly1 ); k4 = (int)(dk4+0.5) & 0x1ff; k5 = (int)(dk5+0.5) & 0x1ff; k6 = (int)(dk6+0.5) & 0x1ff; - assembly = (k6<<18) | (k5<<9) | k4; - xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx ", assembly ); - OUTREG( SEC_STREAM_COLOR_CONVERT2, assembly ); + assembly2 = (k6<<18) | (k5<<9) | k4; + xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx ", assembly2 ); k7 = (int)(dk7+0.5) & 0x1ff; kb = (int)(dkb+0.5) & 0xffff; - assembly = (kb<<9) | k7; - xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly ); - OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly ); + assembly3 = (kb<<9) | k7; + xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly3 ); + + if (psav->IsSecondary) { + OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 ); + } else if (psav->IsPrimary) { + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 ); + } else { + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 ); +#if 0 + sleep(1); + OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 ); + OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 ); +#endif + } } @@ -976,12 +1096,20 @@ SavageSetBlend(ScrnInfoPtr pScrn, int id) SavagePtr psav = SAVPTR(pScrn); if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || - (psav->Chipset == S3_SUPERSAVAGE) || (psav->Chipset == S3_SAVAGE2000) ) { - psav->blendBase = GetBlendForFourCC( id ) << 9; + psav->blendBase = GetBlendForFourCC( id ); xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); - OUTREG( BLEND_CONTROL, psav->blendBase | 0x08 ); + if (psav->IsSecondary) { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); + } else if (psav->IsPrimary) { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); + } else { + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); +#if 0 + OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); +#endif + } } psav->videoFourCC = id; } @@ -1174,11 +1302,11 @@ SavageDisplayVideoNew( } else { - if( - S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && + if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && + (psav->DisplayType == MT_LCD) && !psav->CrtOnly && - !psav->TvOn - ) { + !psav->TvOn) + { drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1; drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1; dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2; @@ -1187,11 +1315,32 @@ SavageDisplayVideoNew( dstBox->y1 += psav->displayYoffset; } - OUTREG(SEC_STREAM_HSCALING, - ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); - /* BUGBUG need to add 00040000 if src stride > 2048 */ - OUTREG(SEC_STREAM_VSCALING, - ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); + if (psav->IsSecondary) { + OUTREG(SEC_STREAM2_HSCALING, + ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); + /* BUGBUG need to add 00040000 if src stride > 2048 */ + OUTREG(SEC_STREAM2_VSCALING, + ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); + } else if (psav->IsPrimary) { + OUTREG(SEC_STREAM_HSCALING, + ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); + /* BUGBUG need to add 00040000 if src stride > 2048 */ + OUTREG(SEC_STREAM_VSCALING, + ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); + } else { + OUTREG(SEC_STREAM_HSCALING, + ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); + /* BUGBUG need to add 00040000 if src stride > 2048 */ + OUTREG(SEC_STREAM_VSCALING, + ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); +#if 0 + OUTREG(SEC_STREAM2_HSCALING, + ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); + /* BUGBUG need to add 00040000 if src stride > 2048 */ + OUTREG(SEC_STREAM2_VSCALING, + ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); +#endif + } } /* @@ -1199,12 +1348,36 @@ SavageDisplayVideoNew( * are 2 bytes/pixel. */ - OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) + if (psav->IsSecondary) { + OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) + & (0x7ffffff & ~BASE_PAD)); + OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); + OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); + OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) + | (dstBox->x2-dstBox->x1) ); + } else if (psav->IsPrimary) { + OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) + & (0x7ffffff & ~BASE_PAD)); + OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); + OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); + OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) + | (dstBox->x2-dstBox->x1) ); + } else { + OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) + & (0x7ffffff & ~BASE_PAD)); + OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); + OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); + OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) + | (dstBox->x2-dstBox->x1) ); +#if 0 + OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) & (0x7ffffff & ~BASE_PAD)); - OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); - OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); - OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) + OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); + OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); + OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) | (dstBox->x2-dstBox->x1) ); +#endif + } #if 0 /* Set color key on primary. */ @@ -1213,7 +1386,7 @@ SavageDisplayVideoNew( #endif /* Set FIFO L2 on second stream. */ - + /* Is CR92 shadowed for crtc2? -- AGD */ if( pPriv->lastKnownPitch != pitch ) { unsigned char cr92; |