summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Deucher <agd5f@yahoo.com>2004-09-30 04:59:37 +0000
committerAlex Deucher <agd5f@yahoo.com>2004-09-30 04:59:37 +0000
commita1ef17bb2cc069511baaefcbe04298c087533d35 (patch)
treef80afeaa07e86672a705fc42eec3a7d5f4c04864 /src
parentcc1882207d72ce67b650b69bb490ba809dec53f5 (diff)
Add Dualhead Support to Mobile savages (MX, IX, Supersavages) Thanks to
Austin Yuan for his help on this.
Diffstat (limited to 'src')
-rw-r--r--src/savage_accel.c284
-rw-r--r--src/savage_bci.h2
-rw-r--r--src/savage_cursor.c100
-rw-r--r--src/savage_driver.c827
-rw-r--r--src/savage_driver.h29
-rw-r--r--src/savage_regs.h12
-rw-r--r--src/savage_streams.c256
-rw-r--r--src/savage_vbe.c140
-rw-r--r--src/savage_vbe.h54
-rw-r--r--src/savage_video.c279
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;