diff options
author | Alex Deucher <agd5f@yahoo.com> | 2004-09-30 04:59:37 +0000 |
---|---|---|
committer | Alex Deucher <agd5f@yahoo.com> | 2004-09-30 04:59:37 +0000 |
commit | a1ef17bb2cc069511baaefcbe04298c087533d35 (patch) | |
tree | f80afeaa07e86672a705fc42eec3a7d5f4c04864 /src/savage_vbe.c | |
parent | cc1882207d72ce67b650b69bb490ba809dec53f5 (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.c | 140 |
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; + } +} |