summaryrefslogtreecommitdiff
path: root/src/savage_vbe.c
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/savage_vbe.c
parentcc1882207d72ce67b650b69bb490ba809dec53f5 (diff)
Add Dualhead Support to Mobile savages (MX, IX, Supersavages) Thanks to
Austin Yuan for his help on this.
Diffstat (limited to 'src/savage_vbe.c')
-rw-r--r--src/savage_vbe.c140
1 files changed, 140 insertions, 0 deletions
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;
+ }
+}