/* * Copyright (C) 2009 RDC Semiconductor Co.,Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * For technical support : * */ #ifdef HAVE_CONFIG_H #include #endif #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" #include "xf86RAC.h" #include "xf86cmap.h" #include "compiler.h" #include "mibstore.h" #include "vgaHW.h" #include "mipointer.h" #include "micmap.h" #include "fb.h" #include "regionstr.h" #include "xf86xv.h" #include #include "vbe.h" #include "xf86PciInfo.h" #include "xf86Pci.h" #include "xf86fbman.h" #include "xaa.h" #include "xaarop.h" #include "xf86Cursor.h" #include "rdc.h" RRateInfo RefreshRateMap[] = { {60.0f, FALSE, 0}, {50.0f, TRUE, 1}, {50.0f, FALSE, 3}, {56.0f, FALSE, 4}, {24.0f, FALSE, 6}, {70.0f, FALSE, 7}, {75.0f, FALSE, 8}, {80.0f, FALSE, 9}, {85.0f, FALSE, 10}, {90.0f, FALSE, 11}, {100.0f, FALSE, 12}, {120.0f, FALSE, 13}, {72.0f, FALSE, 14}, {65.0f, FALSE, 15}}; extern void vRDCOpenKey(ScrnInfoPtr pScrn); extern Bool bRDCRegInit(ScrnInfoPtr pScrn); #ifdef Accel_2D extern Bool bEnable2D(ScrnInfoPtr pScrn, RDCRecPtr pRDC); #endif #ifdef HWC extern Bool bInitHWC(ScrnInfoPtr pScrn, RDCRecPtr pRDC); #endif Bool RDCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode); USHORT usGetVbeModeNum(ScrnInfoPtr pScrn, DisplayModePtr mode); float fDifference(float Value1, float Value2); DisplayModePtr RDCBuildModePool(ScrnInfoPtr pScrn); Bool BTranslateIndexToRefreshRate(UCHAR ucRRateIndex, float *fRefreshRate); char* pcConvertResolutionToString(ULONG ulResolution); DisplayModePtr SearchDisplayModeRecPtr(DisplayModePtr pModePoolHead, CBIOS_ARGUMENTS CBiosArguments); Bool RDCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) { RDCRecPtr pRDC; MODE_PRIVATE *pModePrivate; CBIOS_ARGUMENTS CBiosArguments; CBIOS_Extension CBiosExtension; USHORT usVESAMode; pRDC = RDCPTR(pScrn); pModePrivate = MODE_PRIVATE_PTR(mode); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, InternalLevel, "==Enter RDCSetMode()== \n"); vRDCOpenKey(pScrn); bRDCRegInit(pScrn); CBiosExtension.pCBiosArguments = &CBiosArguments; CBiosExtension.IOAddress = (USHORT)(pRDC->RelocateIO); CBiosExtension.VideoVirtualAddress = (ULONG)(pRDC->FBVirtualAddr); CBiosArguments.reg.x.AX = OEMFunction; CBiosArguments.reg.x.BX = SetDisplay1RefreshRate; CBiosArguments.reg.lh.CL = pModePrivate->ucRRate_ID; CInt10(&CBiosExtension); usVESAMode = usGetVbeModeNum(pScrn, mode); if (pRDC->DeviceInfo.ucNewDeviceID == TVINDEX) { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, ErrorLevel, "==RDCSetMode() VBios Set mode entry\n"); if (pRDC->pVbe == NULL) { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, ErrorLevel, "==RDCSetMode() pVbe = NULL\n"); return FALSE; } if (VBESetVBEMode(pRDC->pVbe, usVESAMode, NULL) == FALSE) { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, ErrorLevel, "==RDCSetMode() VBois set mode Fail\n"); return FALSE; } } else { CBiosArguments.reg.x.AX = VBESetMode; CBiosArguments.reg.x.BX = (0x4000 | usVESAMode); CInt10(&CBiosExtension); } CBiosArguments.reg.x.AX = VBESetGetScanLineLength; CBiosArguments.reg.lh.BL = 0x00; CBiosArguments.reg.x.CX = (USHORT)(pScrn->displayWidth); CInt10(&CBiosExtension); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 7, "==RDCSetMode() Enable 2D== \n"); #ifdef Accel_2D if (!pRDC->noAccel) { if (!bEnable2D(pScrn, pRDC)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Enable 2D failed\n"); pRDC->noAccel = TRUE; } } #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 7, "==RDCSetMode() Enable Cursor== \n"); #ifdef HWC if (!pRDC->noHWC) { if (!bInitHWC(pScrn, pRDC)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Init HWC failed\n"); pRDC->noHWC = TRUE; } } #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, InternalLevel, "==Exit RDCSetMode(), return true== \n"); return (TRUE); } USHORT usGetVbeModeNum(ScrnInfoPtr pScrn, DisplayModePtr mode) { RDCRecPtr pRDC; MODE_PRIVATE *pModePrivate; USHORT usVESAModeNum; UCHAR ucColorDepth = (UCHAR)(pScrn->bitsPerPixel); pRDC = RDCPTR(pScrn); pModePrivate = MODE_PRIVATE_PTR(mode); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DefaultLevel, "==Enter usGetVbeModeNum()== \n"); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, InfoLevel, "==Display Width=0x%x, Height=0x%x, Color Depth=0x%x==\n", mode->HDisplay,mode->VDisplay,pScrn->bitsPerPixel); switch (ucColorDepth) { case 8: usVESAModeNum = pModePrivate->Mode_ID_8bpp; break; case 16: usVESAModeNum = pModePrivate->Mode_ID_16bpp; break; case 32: usVESAModeNum = pModePrivate->Mode_ID_32bpp; break; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DefaultLevel, "==Exit usGetVbeModeNum() return VESA Mode = 0x%x==\n", usVESAModeNum); return usVESAModeNum; } DisplayModePtr RDCBuildModePool(ScrnInfoPtr pScrn) { DisplayModePtr pMode = NULL, pModePoolHead = NULL, pModePoolTail = NULL; CBIOS_ARGUMENTS CBiosArguments; CBIOS_Extension CBiosExtension; RDCRecPtr pRDC = RDCPTR(pScrn); MODE_PRIVATE *pModePrivate; USHORT usSerialNum = 0; USHORT wLCDHorSize, wLCDVerSize; USHORT wVESAModeHorSize, wVESAModeVerSize; BYTE bColorDepth; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DefaultLevel, "==Enter RDCBuildModePool()== \n"); CBiosExtension.pCBiosArguments = &CBiosArguments; CBiosExtension.IOAddress = (USHORT)(pRDC->RelocateIO); CBiosExtension.VideoVirtualAddress = (ULONG)(pRDC->FBVirtualAddr); do { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "Mode serial Num 0x%x\n",usSerialNum); CBiosArguments.reg.x.AX = OEMFunction; CBiosArguments.reg.x.BX = QuerySupportedMode; CBiosArguments.reg.x.CX = usSerialNum++; CInt10(&CBiosExtension); wVESAModeHorSize = (USHORT)(CBiosArguments.reg.ex.EDX & 0x0000FFFF); wVESAModeVerSize = (USHORT)(CBiosArguments.reg.ex.EDX >> 16); if (CBiosArguments.reg.x.AX == VBEFunctionCallSuccessful) { pMode = SearchDisplayModeRecPtr(pModePoolHead, CBiosArguments); if (pMode == NULL) { if (pModePoolHead != NULL) { pModePoolTail->next = xnfalloc(sizeof(DisplayModeRec)); pModePoolTail->next->prev = pModePoolTail; pModePoolTail = pModePoolTail->next; } else { pModePoolHead = xnfalloc(sizeof(DisplayModeRec)); pModePoolHead->prev = NULL; pModePoolTail = pModePoolHead; } pModePoolTail->next = NULL; pModePoolTail->name = pcConvertResolutionToString(CBiosArguments.reg.ex.EDX); pModePoolTail->status = MODE_OK; pModePoolTail->type = M_T_BUILTIN; pModePoolTail->Flags = 0; pModePoolTail->PrivSize = sizeof(MODE_PRIVATE); pModePoolTail->Private = xnfalloc(pModePoolTail->PrivSize); pModePrivate = MODE_PRIVATE_PTR(pModePoolTail); pModePoolTail->Clock = pModePoolTail->SynthClock = CBiosArguments.reg.ex.EDI; pModePoolTail->HDisplay = pModePoolTail->CrtcHDisplay = wVESAModeHorSize; pModePoolTail->VDisplay = pModePoolTail->CrtcVDisplay = wVESAModeVerSize; BTranslateIndexToRefreshRate(CBiosArguments.reg.lh.CH, &(pModePoolTail->VRefresh)); pModePoolTail->PrivFlags = (int)CBiosArguments.reg.x.SI; pModePrivate->ucRRate_ID = CBiosArguments.reg.lh.CH; } else { pModePrivate = MODE_PRIVATE_PTR(pMode); } switch (CBiosArguments.reg.lh.CL) { case 8: pModePrivate->Mode_ID_8bpp = CBiosArguments.reg.x.BX; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "pModePrivate->Mode_ID_8bpp = 0x%x\n",pModePrivate->Mode_ID_8bpp); break; case 16: pModePrivate->Mode_ID_16bpp = CBiosArguments.reg.x.BX; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "pModePrivate->Mode_ID_16bpp = 0x%x\n",pModePrivate->Mode_ID_16bpp); break; case 32: pModePrivate->Mode_ID_32bpp = CBiosArguments.reg.x.BX; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "pModePrivate->Mode_ID_32bpp = 0x%x\n",pModePrivate->Mode_ID_32bpp); break; } } } while (CBiosArguments.reg.x.AX == VBEFunctionCallSuccessful); for (bColorDepth = 0; bColorDepth < 3; bColorDepth++) { CBiosArguments.reg.x.AX = OEMFunction; CBiosArguments.reg.x.BX = QueryLCDPanelSizeMode; CBiosArguments.reg.x.CX = bColorDepth; CInt10(&CBiosExtension); if (CBiosArguments.reg.x.AX == VBEFunctionCallSuccessful) { pMode = SearchDisplayModeRecPtr(pModePoolHead, CBiosArguments); if (pMode == NULL) { if (pModePoolHead != NULL) { pModePoolTail->next = xnfalloc(sizeof(DisplayModeRec)); pModePoolTail->next->prev = pModePoolTail; pModePoolTail = pModePoolTail->next; } else { pModePoolHead = xnfalloc(sizeof(DisplayModeRec)); pModePoolHead->prev = NULL; pModePoolTail = pModePoolHead; } pModePoolTail->next = NULL; pModePoolTail->name = pcConvertResolutionToString(CBiosArguments.reg.ex.EDX); pModePoolTail->status = MODE_OK; pModePoolTail->type = M_T_BUILTIN; pModePoolTail->Flags = 0; pModePoolTail->PrivSize = sizeof(MODE_PRIVATE); pModePoolTail->Private = xnfalloc(pModePoolTail->PrivSize); pModePrivate = MODE_PRIVATE_PTR(pModePoolTail); pModePoolTail->Clock = pModePoolTail->SynthClock = CBiosArguments.reg.ex.EDI; pModePoolTail->HDisplay = pModePoolTail->CrtcHDisplay = (CBiosArguments.reg.ex.EDX & 0x0000FFFF); pModePoolTail->VDisplay = pModePoolTail->CrtcVDisplay = (CBiosArguments.reg.ex.EDX >> 16); BTranslateIndexToRefreshRate(CBiosArguments.reg.lh.CH, &(pModePoolTail->VRefresh)); pModePoolTail->PrivFlags = (int)CBiosArguments.reg.x.SI | LCD_TIMING; pModePrivate->ucRRate_ID = CBiosArguments.reg.lh.CH; } else { pModePrivate = MODE_PRIVATE_PTR(pMode); } switch (CBiosArguments.reg.lh.CL) { case 8: pModePrivate->Mode_ID_8bpp = CBiosArguments.reg.x.BX; break; case 16: pModePrivate->Mode_ID_16bpp = CBiosArguments.reg.x.BX; break; case 32: pModePrivate->Mode_ID_32bpp = CBiosArguments.reg.x.BX; break; } } } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DefaultLevel, "==Exit RDCBuildModePool()== pModePoolHead = 0x%x\n", pModePoolHead); return pModePoolHead; } Bool BTranslateIndexToRefreshRate(UCHAR ucRRateIndex, float *fRefreshRate) { int i; for (i = 0; i < sizeof(RefreshRateMap)/sizeof(RRateInfo); i++) { if (RefreshRateMap[i].ucRRateIndex == ucRRateIndex) { *fRefreshRate = RefreshRateMap[i].fRefreshRate; return (TRUE); } } return (FALSE); } char* pcConvertResolutionToString(ULONG ulResolution) { USHORT usHorResolution = (USHORT)(ulResolution & 0x0000FFFF); USHORT usVerResolution = (USHORT)(ulResolution >> 16); USHORT usTemp; int iIndex, iStringSize, i; char *pcResolution; pcResolution = xnfalloc(10); iIndex = 0; iStringSize = 1; usTemp = usHorResolution; while ((usTemp/10) > 0) { iStringSize++; usTemp /= 10; } usTemp = usHorResolution; for ( i = 1 ; i <= iStringSize; i++) { pcResolution[iIndex+ iStringSize - i] = (usTemp%10) + 0x30; usTemp /= 10; } iIndex += iStringSize; pcResolution[iIndex] = 'x'; iIndex++; iStringSize = 1; usTemp = usVerResolution; while ((usTemp/10) > 0) { iStringSize++; usTemp /= 10; } usTemp = usVerResolution; for ( i = 1 ; i <= iStringSize; i++) { pcResolution[iIndex+ iStringSize - i] = (usTemp%10) + 0x30; usTemp /= 10; } iIndex += iStringSize; pcResolution[iIndex] = '\0'; return pcResolution; } DisplayModePtr SearchDisplayModeRecPtr(DisplayModePtr pModePoolHead, CBIOS_ARGUMENTS CBiosArguments) { DisplayModePtr pMode = pModePoolHead; MODE_PRIVATE *pModePrivate; xf86DrvMsgVerb(0, X_INFO, InternalLevel, "==Enter SearchDisplayModeRecPtr(CH = 0x%02X, EDX = 0x%08X, SI = 0x%X, EDI = %d)== \n", CBiosArguments.reg.lh.CH, CBiosArguments.reg.ex.EDX, CBiosArguments.reg.x.SI, CBiosArguments.reg.ex.EDI); while(pMode != NULL) { pModePrivate = MODE_PRIVATE_PTR(pMode); if ((pModePrivate->ucRRate_ID == CBiosArguments.reg.lh.CH) && (pMode->HDisplay == (int)(CBiosArguments.reg.ex.EDX & 0x0000FFFF)) && (pMode->VDisplay == (int)(CBiosArguments.reg.ex.EDX >>16)) && ((pMode->PrivFlags & 0xFFFF) == (int)CBiosArguments.reg.x.SI) && (pMode->Clock == CBiosArguments.reg.ex.EDI)) { xf86DrvMsgVerb(0, X_INFO, InternalLevel, "==Exit1 SearchDisplayModeRecPtr()== \n"); return pMode; } pMode = pMode->next; } xf86DrvMsgVerb(0, X_INFO, InternalLevel, "==Exit2 SearchDisplayModeRecPtr()== \n"); return NULL; }