/* $XFree86$ */ /* $XdotOrg$ */ /* * Mode initializing code (CRT2 section) * for SiS 300/305/540/630/730, * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX], * XGI V3XT/V5/V8, Z7 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x) * * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria * * If distributed as part of the Linux kernel, the following license terms * apply: * * * 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 2 of the named License, * * or 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, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * Otherwise, the following license terms apply: * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1) Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2) Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3) The name of the author may not be used to endorse or promote products * * derived from this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Author: Thomas Winischhofer * * Formerly based on non-functional code-fragements for 300 series by SiS, Inc. * Used by permission. * */ #if 1 #define SET_EMI /* 302LV/ELV: Set EMI values */ #endif #if 1 #define SET_PWD /* 301/302LV: Set PWD */ #endif #define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */ #define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */ #define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */ #include "init301.h" #ifdef CONFIG_FB_SIS_300 #include "oem300.h" #endif #ifdef CONFIG_FB_SIS_315 #include "oem310.h" #endif #define SiS_I2CDELAY 1000 #define SiS_I2CDELAYSHORT 150 static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr); static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val); /*********************************************/ /* HELPER: Lock/Unlock CRT2 */ /*********************************************/ void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType == XGI_20) return; else if(SiS_Pr->ChipType >= SIS_315H) SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01); else SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01); } static void SiS_LockCRT2(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType == XGI_20) return; else if(SiS_Pr->ChipType >= SIS_315H) SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE); else SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE); } /*********************************************/ /* HELPER: Write SR11 */ /*********************************************/ static void SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR) { if(SiS_Pr->ChipType >= SIS_661) { DataAND &= 0x0f; DataOR &= 0x0f; } SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR); } /*********************************************/ /* HELPER: Get Pointer to LCD structure */ /*********************************************/ #ifdef CONFIG_FB_SIS_315 static unsigned char * GetLCDStructPtr661(struct SiS_Private *SiS_Pr) { unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned char *myptr = NULL; unsigned short romindex = 0, reg = 0, idx = 0; /* Use the BIOS tables only for LVDS panels; TMDS is unreliable * due to the variaty of panels the BIOS doesn't know about. * Exception: If the BIOS has better knowledge (such as in case * of machines with a 301C and a panel that does not support DDC) * use the BIOS data as well. */ if((SiS_Pr->SiS_ROMNew) && ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) { if(SiS_Pr->ChipType < SIS_661) reg = 0x3c; else reg = 0x7d; idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26; if(idx < (8*26)) { myptr = (unsigned char *)&SiS_LCDStruct661[idx]; } romindex = SISGETROMW(0x100); if(romindex) { romindex += idx; myptr = &ROMAddr[romindex]; } } return myptr; } static unsigned short GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr) { unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned short romptr = 0; /* Use the BIOS tables only for LVDS panels; TMDS is unreliable * due to the variaty of panels the BIOS doesn't know about. * Exception: If the BIOS has better knowledge (such as in case * of machines with a 301C and a panel that does not support DDC) * use the BIOS data as well. */ if((SiS_Pr->SiS_ROMNew) && ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) { romptr = SISGETROMW(0x102); romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize); } return romptr; } #endif /*********************************************/ /* Adjust Rate for CRT2 */ /*********************************************/ static bool SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI, unsigned short *i) { unsigned short checkmask=0, modeid, infoflag; modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID; if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { checkmask |= SupportRAMDAC2; if(SiS_Pr->ChipType >= SIS_315H) { checkmask |= SupportRAMDAC2_135; if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { checkmask |= SupportRAMDAC2_162; if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) { checkmask |= SupportRAMDAC2_202; } } } } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { checkmask |= SupportLCD; if(SiS_Pr->ChipType >= SIS_315H) { if(SiS_Pr->SiS_VBType & VB_SISVB) { if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) { if(modeid == 0x2e) checkmask |= Support64048060Hz; } } } } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { checkmask |= SupportHiVision; } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) { checkmask |= SupportTV; if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { checkmask |= SupportTV1024; if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { checkmask |= SupportYPbPr750p; } } } } } else { /* LVDS */ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { checkmask |= SupportCHTV; } } if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { checkmask |= SupportLCD; } } /* Look backwards in table for matching CRT2 mode */ for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) { infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag; if(infoflag & checkmask) return true; if((*i) == 0) break; } /* Look through the whole mode-section of the table from the beginning * for a matching CRT2 mode if no mode was found yet. */ for((*i) = 0; ; (*i)++) { if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break; infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag; if(infoflag & checkmask) return true; } return false; } /*********************************************/ /* Get rate index */ /*********************************************/ unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex) { unsigned short RRTI,i,backup_i; unsigned short modeflag,index,temp,backupindex; static const unsigned short LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }; /* Do NOT check for UseCustomMode here, will skrew up FIFO */ if(ModeNo == 0xfe) return 0; if(ModeNo <= 0x13) { modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; } else { modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; } if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { if(modeflag & HalfDCLK) return 0; } } if(ModeNo < 0x14) return 0xFFFF; index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F; backupindex = index; if(index > 0) index--; if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0; else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0; } if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) { temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)]; if(index > temp) index = temp; } } } else { if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0; if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0; } } } RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID; if(SiS_Pr->ChipType >= SIS_315H) { if(!(SiS_Pr->SiS_VBInfo & DriverMode)) { if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) || (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) { if(backupindex <= 1) RRTI++; } } } i = 0; do { if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break; temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag; temp &= ModeTypeMask; if(temp < SiS_Pr->SiS_ModeType) break; i++; index--; } while(index != 0xFFFF); if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag; if(temp & InterlaceMode) i++; } } i--; if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) { backup_i = i; if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) { i = backup_i; } } return (RRTI + i); } /*********************************************/ /* STORE CRT2 INFO in CR34 */ /*********************************************/ static void SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo) { unsigned short temp1, temp2; /* Store CRT1 ModeNo in CR34 */ SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo); temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8; temp2 = ~(SetInSlaveMode >> 8); SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1); } /*********************************************/ /* HELPER: GET SOME DATA FROM BIOS ROM */ /*********************************************/ #ifdef CONFIG_FB_SIS_300 static bool SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr) { unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned short temp,temp1; if(SiS_Pr->SiS_UseROM) { if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f); temp1 = SISGETROMW(0x23b); if(temp1 & temp) return true; } } return false; } static bool SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr) { unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned short temp,temp1; if(SiS_Pr->SiS_UseROM) { if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f); temp1 = SISGETROMW(0x23d); if(temp1 & temp) return true; } } return false; } #endif /*********************************************/ /* HELPER: DELAY FUNCTIONS */ /*********************************************/ void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime) { while (delaytime-- > 0) SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05); } #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) static void SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay) { SiS_DDC2Delay(SiS_Pr, delay * 36); } #endif #ifdef CONFIG_FB_SIS_315 static void SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay) { while(delay--) { SiS_GenericDelay(SiS_Pr, 6623); } } #endif #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) static void SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay) { while(delay--) { SiS_GenericDelay(SiS_Pr, 66); } } #endif static void SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime) { #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned short PanelID, DelayIndex, Delay=0; #endif if(SiS_Pr->ChipType < SIS_315H) { #ifdef CONFIG_FB_SIS_300 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7; if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12; } DelayIndex = PanelID >> 4; if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) { Delay = 3; } else { if(DelayTime >= 2) DelayTime -= 2; if(!(DelayTime & 0x01)) { Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0]; } else { Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1]; } if(SiS_Pr->SiS_UseROM) { if(ROMAddr[0x220] & 0x40) { if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225]; else Delay = (unsigned short)ROMAddr[0x226]; } } } SiS_ShortDelay(SiS_Pr, Delay); #endif /* CONFIG_FB_SIS_300 */ } else { #ifdef CONFIG_FB_SIS_315 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->ChipType <= SIS_315PRO) || (SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_ROMNew)) { if(!(DelayTime & 0x01)) { SiS_DDC2Delay(SiS_Pr, 0x1000); } else { SiS_DDC2Delay(SiS_Pr, 0x4000); } } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) || (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) { if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12; } if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { DelayIndex = PanelID & 0x0f; } else { DelayIndex = PanelID >> 4; } if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) { Delay = 3; } else { if(DelayTime >= 2) DelayTime -= 2; if(!(DelayTime & 0x01)) { Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0]; } else { Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1]; } if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { if(ROMAddr[0x13c] & 0x40) { if(!(DelayTime & 0x01)) { Delay = (unsigned short)ROMAddr[0x17e]; } else { Delay = (unsigned short)ROMAddr[0x17f]; } } } } SiS_ShortDelay(SiS_Pr, Delay); } } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */ DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4; if(!(DelayTime & 0x01)) { Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0]; } else { Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1]; } Delay <<= 8; SiS_DDC2Delay(SiS_Pr, Delay); } #endif /* CONFIG_FB_SIS_315 */ } } #ifdef CONFIG_FB_SIS_315 static void SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop) { int i; for(i = 0; i < DelayLoop; i++) { SiS_PanelDelay(SiS_Pr, DelayTime); } } #endif /*********************************************/ /* HELPER: WAIT-FOR-RETRACE FUNCTIONS */ /*********************************************/ void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr) { unsigned short watchdog; if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return; if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return; watchdog = 65535; while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog); watchdog = 65535; while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); } #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) static void SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg) { unsigned short watchdog; watchdog = 65535; while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog); watchdog = 65535; while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog); } #endif static void SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType < SIS_315H) { #ifdef CONFIG_FB_SIS_300 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return; } if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) { SiS_WaitRetrace1(SiS_Pr); } else { SiS_WaitRetrace2(SiS_Pr, 0x25); } #endif } else { #ifdef CONFIG_FB_SIS_315 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) { SiS_WaitRetrace1(SiS_Pr); } else { SiS_WaitRetrace2(SiS_Pr, 0x30); } #endif } } static void SiS_VBWait(struct SiS_Private *SiS_Pr) { unsigned short tempal,temp,i,j; temp = 0; for(i = 0; i < 3; i++) { for(j = 0; j < 100; j++) { tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da); if(temp & 0x01) { if((tempal & 0x08)) continue; else break; } else { if(!(tempal & 0x08)) continue; else break; } } temp ^= 0x01; } } static void SiS_VBLongWait(struct SiS_Private *SiS_Pr) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { SiS_VBWait(SiS_Pr); } else { SiS_WaitRetrace1(SiS_Pr); } } /*********************************************/ /* HELPER: MISC */ /*********************************************/ #ifdef CONFIG_FB_SIS_300 static bool SiS_Is301B(struct SiS_Private *SiS_Pr) { if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true; return false; } #endif static bool SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType == SIS_730) { if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true; } if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true; return false; } bool SiS_IsDualEdge(struct SiS_Private *SiS_Pr) { #ifdef CONFIG_FB_SIS_315 if(SiS_Pr->ChipType >= SIS_315H) { if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) { if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true; } } #endif return false; } bool SiS_IsVAMode(struct SiS_Private *SiS_Pr) { #ifdef CONFIG_FB_SIS_315 unsigned short flag; if(SiS_Pr->ChipType >= SIS_315H) { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true; } #endif return false; } #ifdef CONFIG_FB_SIS_315 static bool SiS_IsVAorLCD(struct SiS_Private *SiS_Pr) { if(SiS_IsVAMode(SiS_Pr)) return true; if(SiS_CRT2IsLCD(SiS_Pr)) return true; return false; } #endif static bool SiS_IsDualLink(struct SiS_Private *SiS_Pr) { #ifdef CONFIG_FB_SIS_315 if(SiS_Pr->ChipType >= SIS_315H) { if((SiS_CRT2IsLCD(SiS_Pr)) || (SiS_IsVAMode(SiS_Pr))) { if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true; } } #endif return false; } #ifdef CONFIG_FB_SIS_315 static bool SiS_TVEnabled(struct SiS_Private *SiS_Pr) { if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true; if(SiS_Pr->SiS_VBType & VB_SISYPBPR) { if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true; } return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_LCDAEnabled(struct SiS_Private *SiS_Pr) { if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true; return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr) { if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) { if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true; } return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr) { unsigned short flag; if(SiS_Pr->ChipType == SIS_650) { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0; /* Check for revision != A0 only */ if((flag == 0xe0) || (flag == 0xc0) || (flag == 0xb0) || (flag == 0x90)) return false; } else if(SiS_Pr->ChipType >= SIS_661) return false; return true; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_IsYPbPr(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType >= SIS_315H) { /* YPrPb = 0x08 */ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true; } return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_IsChScart(struct SiS_Private *SiS_Pr) { if(SiS_Pr->ChipType >= SIS_315H) { /* Scart = 0x04 */ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true; } return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr) { unsigned short flag; if(SiS_Pr->ChipType >= SIS_315H) { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); if(flag & SetCRT2ToTV) return true; flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if(flag & EnableCHYPbPr) return true; /* = YPrPb = 0x08 */ if(flag & EnableCHScart) return true; /* = Scart = 0x04 - TW */ } else { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); if(flag & SetCRT2ToTV) return true; } return false; } #endif #ifdef CONFIG_FB_SIS_315 static bool SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr) { unsigned short flag; if(SiS_Pr->ChipType >= SIS_315H) { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); if(flag & SetCRT2ToLCD) return true; flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if(flag & SetToLCDA) return true; } else { flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); if(flag & SetCRT2ToLCD) return true; } return false; } #endif static bool SiS_HaveBridge(struct SiS_Private *SiS_Pr) { unsigned short flag; if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { return true; } else if(SiS_Pr->SiS_VBType & VB_SISVB) { flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); if((flag == 1) || (flag == 2)) return true; } return false; } static bool SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr) { unsigned short flag; if(SiS_HaveBridge(SiS_Pr)) { flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00); if(SiS_Pr->ChipType < SIS_315H) { flag &= 0xa0; if((flag == 0x80) || (flag == 0x20)) return true; } else { flag &= 0x50; if((flag == 0x40) || (flag == 0x10)) return true; } } return false; } static bool SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr) { unsigned short flag1; flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); if(flag1 & (SetInSlaveMode >> 8)) return true; return false; } /*********************************************/ /* GET VIDEO BRIDGE CONFIG INFO */ /*********************************************/ /* Setup general purpose IO for Chrontel communication */ #ifdef CONFIG_FB_SIS_300 void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo) { unsigned int acpibase; unsigned short temp; if(!(SiS_Pr->SiS_ChSW)) return; acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74); acpibase &= 0xFFFF; if(!acpibase) return; temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */ temp &= 0xFEFF; SiS_SetRegShort((acpibase + 0x3c), temp); temp = SiS_GetRegShort((acpibase + 0x3c)); temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */ temp &= 0xFEFF; if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100; SiS_SetRegShort((acpibase + 0x3a), temp); temp = SiS_GetRegShort((acpibase + 0x3a)); } #endif void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, int checkcrt2mode) { unsigned short tempax, tempbx, temp; unsigned short modeflag, resinfo = 0; SiS_Pr->SiS_SetFlag = 0; modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex); SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask; if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) { resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; } tempbx = 0; if(SiS_HaveBridge(SiS_Pr)) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); tempbx |= temp; tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8; tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV); tempbx |= tempax; #ifdef CONFIG_FB_SIS_315 if(SiS_Pr->ChipType >= SIS_315H) { if(SiS_Pr->SiS_VBType & VB_SISLCDA) { if(ModeNo == 0x03) { /* Mode 0x03 is never in driver mode */ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf); } if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) { /* Reset LCDA setting if not driver mode */ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); } if(IS_SIS650) { if(SiS_Pr->SiS_UseLCDA) { if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) { if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) { SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA)); } } } } temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) { tempbx |= SetCRT2ToLCDA; } } if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */ tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision); if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0; if(temp == 0x60) tempbx |= SetCRT2ToHiVision; else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) { tempbx |= SetCRT2ToYPbPr525750; } } } if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if(temp & SetToLCDA) { tempbx |= SetCRT2ToLCDA; } if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(temp & EnableCHYPbPr) { tempbx |= SetCRT2ToCHYPbPr; } } } } #endif /* CONFIG_FB_SIS_315 */ if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) { tempbx &= ~(SetCRT2ToRAMDAC); } if(SiS_Pr->SiS_VBType & VB_SISVB) { temp = SetCRT2ToSVIDEO | SetCRT2ToAVIDEO | SetCRT2ToSCART | SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToHiVision | SetCRT2ToYPbPr525750; } else { if(SiS_Pr->ChipType >= SIS_315H) { if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { temp = SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToCHYPbPr; } else { temp = SetCRT2ToLCDA | SetCRT2ToLCD; } } else { if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { temp = SetCRT2ToTV | SetCRT2ToLCD; } else { temp = SetCRT2ToLCD; } } } if(!(tempbx & temp)) { tempax = DisableCRT2Display; tempbx = 0; } if(SiS_Pr->SiS_VBType & VB_SISVB) { unsigned short clearmask = ( DriverMode | DisableCRT2Display | LoadDACFlag | SetNotSimuMode | SetInSlaveMode | SetPALTV | SwitchCRT2 | SetSimuScanMode ); if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA); if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC); if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD); if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART); if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision); if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750); } else { if(SiS_Pr->ChipType >= SIS_315H) { if(tempbx & SetCRT2ToLCDA) { tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode); } } if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(tempbx & SetCRT2ToTV) { tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode); } } if(tempbx & SetCRT2ToLCD) { tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode); } if(SiS_Pr->ChipType >= SIS_315H) { if(tempbx & SetCRT2ToLCDA) { tempbx |= SetCRT2ToLCD; } } } if(tempax & DisableCRT2Display) { if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) { tempbx = SetSimuScanMode | DisableCRT2Display; } } if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode; /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */ if(SiS_Pr->SiS_ModeType <= ModeVGA) { if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) || ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) { modeflag &= (~CRT2Mode); } } if(!(tempbx & SetSimuScanMode)) { if(tempbx & SwitchCRT2) { if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { if(resinfo != SIS_RI_1600x1200) { tempbx |= SetSimuScanMode; } } } else { if(SiS_BridgeIsEnabled(SiS_Pr)) { if(!(tempbx & DriverMode)) { if(SiS_BridgeInSlavemode(SiS_Pr)) { tempbx |= SetSimuScanMode; } } } } } if(!(tempbx & DisableCRT2Display)) { if(tempbx & DriverMode) { if(tempbx & SetSimuScanMode) { if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { if(resinfo != SIS_RI_1600x1200) { tempbx |= SetInSlaveMode; } } } } else { tempbx |= SetInSlaveMode; } } } SiS_Pr->SiS_VBInfo = tempbx; #ifdef CONFIG_FB_SIS_300 if(SiS_Pr->ChipType == SIS_630) { SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo); } #endif #if 0 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n", SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag); #endif } /*********************************************/ /* DETERMINE YPbPr MODE */ /*********************************************/ void SiS_SetYPbPr(struct SiS_Private *SiS_Pr) { unsigned char temp; /* Note: This variable is only used on 30xLV systems. * CR38 has a different meaning on LVDS/CH7019 systems. * On 661 and later, these bits moved to CR35. * * On 301, 301B, only HiVision 1080i is supported. * On 30xLV, 301C, only YPbPr 1080i is supported. */ SiS_Pr->SiS_YPbPr = 0; if(SiS_Pr->ChipType >= SIS_661) return; if(SiS_Pr->SiS_VBType) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { SiS_Pr->SiS_YPbPr = YPbPrHiVision; } } if(SiS_Pr->ChipType >= SIS_315H) { if(SiS_Pr->SiS_VBType & VB_SISYPBPR) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if(temp & 0x08) { switch((temp >> 4)) { case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break; case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break; case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break; case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break; } } } } } /*********************************************/ /* DETERMINE TVMode flag */ /*********************************************/ void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex) { unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; unsigned short temp, temp1, resinfo = 0, romindex = 0; unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect; SiS_Pr->SiS_TVMode = 0; if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return; if(SiS_Pr->UseCustomMode) return; if(ModeNo > 0x13) { resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; } if(SiS_Pr->ChipType < SIS_661) { if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL; if(SiS_Pr->SiS_VBType & VB_SISVB) { temp = 0; if((SiS_Pr->ChipType == SIS_630) || (SiS_Pr->ChipType == SIS_730)) { temp = 0x35; romindex = 0xfe; } else if(SiS_Pr->ChipType >= SIS_315H) { temp = 0x38; if(SiS_Pr->ChipType < XGI_20) { romindex = 0xf3; if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b; } } if(temp) { if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) { OutputSelect = ROMAddr[romindex]; if(!(OutputSelect & EnablePALMN)) { SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F); } } temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp); if(SiS_Pr->SiS_TVMode & TVSetPAL) { if(temp1 & EnablePALM) { /* 0x40 */ SiS_Pr->SiS_TVMode |= TVSetPALM; SiS_Pr->SiS_TVMode &= ~TVSetPAL; } else if(temp1 & EnablePALN) { /* 0x80 */ SiS_Pr->SiS_TVMode |= TVSetPALN; } } else { if(temp1 & EnableNTSCJ) { /* 0x40 */ SiS_Pr->SiS_TVMode |= TVSetNTSCJ; } } } /* Translate HiVision/YPbPr to our new flags */ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p; else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p; else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision; else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i; if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) { SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision; SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750; } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) { SiS_Pr->SiS_TVMode |= TVSetPAL; } } } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { if(SiS_Pr->SiS_CHOverScan) { if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) { SiS_Pr->SiS_TVMode |= TVSetCHOverScan; } } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79); if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) { SiS_Pr->SiS_TVMode |= TVSetCHOverScan; } } if(SiS_Pr->SiS_CHSOverScan) { SiS_Pr->SiS_TVMode |= TVSetCHOverScan; } } if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); if(SiS_Pr->SiS_TVMode & TVSetPAL) { if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM; else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN; } else { if(temp & EnableNTSCJ) { SiS_Pr->SiS_TVMode |= TVSetNTSCJ; } } } } } else { /* 661 and later */ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); if(temp1 & 0x01) { SiS_Pr->SiS_TVMode |= TVSetPAL; if(temp1 & 0x08) { SiS_Pr->SiS_TVMode |= TVSetPALN; } else if(temp1 & 0x04) { if(SiS_Pr->SiS_VBType & VB_SISVB) { SiS_Pr->SiS_TVMode &= ~TVSetPAL; } SiS_Pr->SiS_TVMode |= TVSetPALM; } } else { if(temp1 & 0x02) { SiS_Pr->SiS_TVMode |= TVSetNTSCJ; } } if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { if(SiS_Pr->SiS_CHOverScan) { if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) { SiS_Pr->SiS_TVMode |= TVSetCHOverScan; } } } if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { temp1 &= 0xe0; if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i; else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p; else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p; } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL); } if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) { if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) { SiS_Pr->SiS_TVMode |= TVAspect169; } else { temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39); if(temp1 & 0x02) { if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) { SiS_Pr->SiS_TVMode |= TVAspect169; } else { SiS_Pr->SiS_TVMode |= TVAspect43LB; } } else { SiS_Pr->SiS_TVMode |= TVAspect43; } } } } } if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL; if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { SiS_Pr->SiS_TVMode |= TVSetPAL; SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ); } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) { SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN); } } if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) { SiS_Pr->SiS_TVMode |= TVSetTVSimuMode; } } if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { if(resinfo == SIS_RI_1024x768) { if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) { SiS_Pr->SiS_TVMode |= TVSet525p1024; } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) { SiS_Pr->SiS_TVMode |= TVSetNTSC1024; } } } SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO; if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) { SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) { if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; } } } SiS_Pr->SiS_VBInfo &= ~SetPALTV; } /*********************************************/ /* GET LCD INFO */ /*********************************************/ static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr) { unsigned short temp = SiS_Pr->SiS_LCDResInfo; /* Translate my LCDResInfo to BIOS value */ switch(temp) { case Panel_1280x768_2: temp = Panel_1280x768; break; case Panel_1280x800_2: temp = Panel_1280x800; break; case Panel_1280x854: temp = Panel661_1280x854; break; } return temp; } static void SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr) { #ifdef CONFIG_FB_SIS_315 unsigned char *ROMAddr; unsigned short temp; if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) { if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) { SiS_Pr->SiS_NeedRomModeData = true; SiS_Pr->PanelHT = temp; } if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) { SiS_Pr->SiS_NeedRomModeData = true; SiS_Pr->PanelVT = temp; } SiS_Pr->PanelHRS = SISGETROMW(10); SiS_Pr->PanelHRE = SISGETROMW(12); SiS_Pr->PanelVRS = SISGETROMW(14); SiS_Pr->PanelVRE = SISGETROMW(16); SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315; SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK = SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]); SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B = SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19]; SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C = SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20]; } #endif } static void SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo, const unsigned char *nonscalingmodes) { int i = 0; while(nonscalingmodes[i] != 0xff) { if(nonscalingmodes[i++] == resinfo) { if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) || (SiS_Pr->UsePanelScaler == -1)) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; } } } void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex) { unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0; bool panelcanscale = false; #ifdef CONFIG_FB_SIS_300 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; static const unsigned char SiS300SeriesLCDRes[] = { 0, 1, 2, 3, 7, 4, 5, 8, 0, 0, 10, 0, 0, 0, 0, 15 }; #endif #ifdef CONFIG_FB_SIS_315 unsigned char *myptr = NULL; #endif SiS_Pr->SiS_LCDResInfo = 0; SiS_Pr->SiS_LCDTypeInfo = 0; SiS_Pr->SiS_LCDInfo = 0; SiS_Pr->PanelHRS = 999; /* HSync start */ SiS_Pr->PanelHRE = 999; /* HSync end */ SiS_Pr->PanelVRS = 999; /* VSync start */ SiS_Pr->PanelVRE = 999; /* VSync end */ SiS_Pr->SiS_NeedRomModeData = false; /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */ SiS_Pr->Alternate1600x1200 = false; if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return; modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex); if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) { resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal; modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal; } temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); /* For broken BIOSes: Assume 1024x768 */ if(temp == 0) temp = 0x02; if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) { SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2; } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) { SiS_Pr->SiS_LCDTypeInfo = temp >> 4; } else { SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1; } temp &= 0x0f; #ifdef CONFIG_FB_SIS_300 if(SiS_Pr->ChipType < SIS_315H) { /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */ if(SiS_Pr->SiS_VBType & VB_SIS301) { if(temp < 0x0f) temp &= 0x07; } /* Translate 300 series LCDRes to 315 series for unified usage */ temp = SiS300SeriesLCDRes[temp]; } #endif /* Translate to our internal types */ #ifdef CONFIG_FB_SIS_315 if(SiS_Pr->ChipType == SIS_550) { if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */ else if(temp == Panel310_320x240_2) temp = Panel_320x240_2; else if(temp == Panel310_320x240_3) temp = Panel_320x240_3; } else if(SiS_Pr->ChipType >= SIS_661) { if(temp == Panel661_1280x854) temp = Panel_1280x854; } #endif if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */ if(temp == Panel310_1280x768) { temp = Panel_1280x768_2; } if(SiS_Pr->SiS_ROMNew) { if(temp == Panel661_1280x800) { temp = Panel_1280x800_2; } } } SiS_Pr->SiS_LCDResInfo = temp; #ifdef CONFIG_FB_SIS_300 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { SiS_Pr->SiS_LCDResInfo = Panel_Barco1366; } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) { SiS_Pr->SiS_LCDResInfo = Panel_848x480; } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) { SiS_Pr->SiS_LCDResInfo = Panel_856x480; } } #endif if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301) SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301; } else { if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS) SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS; } temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); SiS_Pr->SiS_LCDInfo = temp & ~0x000e; /* Need temp below! */ /* These must/can't scale no matter what */ switch(SiS_Pr->SiS_LCDResInfo) { case Panel_320x240_1: case Panel_320x240_2: case Panel_320x240_3: case Panel_1280x960: SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD; break; case Panel_640x480: SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD); if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD; else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD; /* Dual link, Pass 1:1 BIOS default, etc. */ #ifdef CONFIG_FB_SIS_315 if(SiS_Pr->ChipType >= SIS_661) { if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11; } if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) { if(SiS_Pr->SiS_ROMNew) { if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink; } else if((myptr = GetLCDStructPtr661(SiS_Pr))) { if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink; } } } else if(SiS_Pr->ChipType >= SIS_315H) { if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11; } if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) { SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit); temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit; if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) { if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink; } } else if(!(SiS_Pr->SiS_ROMNew)) { if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) { if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) && (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) { SiS_Pr->SiS_LCDInfo |= LCDDualLink; } if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) || (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) || (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) || (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) { SiS_Pr->SiS_LCDInfo |= LCDDualLink; } } } } #endif /* Pass 1:1 */ if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) { /* Always center screen on LVDS (if scaling is disabled) */ SiS_Pr->SiS_LCDInfo &= ~LCDPass11; } else if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* Always center screen on SiS LVDS (if scaling is disabled) */ SiS_Pr->SiS_LCDInfo &= ~LCDPass11; } else { /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */ if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11; if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11; } } SiS_Pr->PanelVCLKIdx300 = VCLK65_300; SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; switch(SiS_Pr->SiS_LCDResInfo) { case Panel_320x240_1: case Panel_320x240_2: case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480; SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx300 = VCLK28; SiS_Pr->PanelVCLKIdx315 = VCLK28; break; case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx300 = VCLK28; SiS_Pr->PanelVCLKIdx315 = VCLK28; break; case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600; SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628; SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128; SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4; SiS_Pr->PanelVCLKIdx300 = VCLK40; SiS_Pr->PanelVCLKIdx315 = VCLK40; break; case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600; SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800; SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136; SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6; SiS_Pr->PanelVCLKIdx300 = VCLK65_300; SiS_Pr->PanelVCLKIdx315 = VCLK65_315; break; case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136; SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; if(SiS_Pr->ChipType < SIS_315H) { SiS_Pr->PanelHRS = 23; SiS_Pr->PanelVRE = 5; } SiS_Pr->PanelVCLKIdx300 = VCLK65_300; SiS_Pr->PanelVCLKIdx315 = VCLK65_315; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768; SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136; SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; if(SiS_Pr->ChipType < SIS_315H) { SiS_Pr->PanelHRS = 23; SiS_Pr->PanelVRE = 5; } SiS_Pr->PanelVCLKIdx300 = VCLK65_300; SiS_Pr->PanelVCLKIdx315 = VCLK65_315; break; case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864; break; case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720; SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750; SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40; SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5; SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720; /* Data above for TMDS (projector); get from BIOS for LVDS */ SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768; if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806; SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */ SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */ } else { SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112; SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; SiS_Pr->PanelVCLKIdx300 = VCLK81_300; SiS_Pr->PanelVCLKIdx315 = VCLK81_315; } break; case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768; SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800; SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816; SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24; SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800; SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854; SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861; SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112; SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960; SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000; SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300; SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315; if(resinfo == SIS_RI_1280x1024) { SiS_Pr->PanelVCLKIdx300 = VCLK100_300; SiS_Pr->PanelVCLKIdx315 = VCLK100_315; } break; case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300; SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250; SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192; SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; SiS_Pr->PanelVCLKIdx315 = VCLK162_315; if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235; SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32; SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4; SiS_Pr->PanelVCLKIdx315 = VCLK130_315; SiS_Pr->Alternate1600x1200 = true; } } else if(SiS_Pr->SiS_IF_DEF_LVDS) { SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320; SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999; SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999; } SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050; SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066; SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76; SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; SiS_Pr->PanelVCLKIdx315 = VCLK121_315; SiS_GetLCDInfoBIOS(SiS_Pr); break; case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; break; case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480; SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525; break; case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480; SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525; break; case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX; SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY; SiS_Pr->PanelHT = SiS_Pr->CHTotal; SiS_Pr->PanelVT = SiS_Pr->CVTotal; if(SiS_Pr->CP_PreferredIndex != -1) { SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex]; SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes; SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS; SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes; SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS; if(SiS_Pr->CP_PrefClock) { int idx; SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315; SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300; if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300; else idx = VCLK_CUSTOM_315; SiS_Pr->SiS_VCLKData[idx].CLOCK = SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock; SiS_Pr->SiS_VCLKData[idx].SR2B = SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B; SiS_Pr->SiS_VCLKData[idx].SR2C = SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C; } } break; default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; break; } /* Special cases */ if( (SiS_Pr->SiS_IF_DEF_FSTN) || (SiS_Pr->SiS_IF_DEF_DSTN) || (SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024) || (SiS_Pr->SiS_CustomT == CUT_PANEL848) || (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) { SiS_Pr->PanelHRS = 999; SiS_Pr->PanelHRE = 999; } if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024) || (SiS_Pr->SiS_CustomT == CUT_PANEL848) || (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) { SiS_Pr->PanelVRS = 999; SiS_Pr->PanelVRE = 999; } /* DontExpand overrule */ if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) { /* No scaling for this mode on any panel (LCD=CRT2)*/ SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } switch(SiS_Pr->SiS_LCDResInfo) { case Panel_Custom: case Panel_1152x864: case Panel_1280x768: /* TMDS only */ SiS_Pr->SiS_LCDInfo |= DontExpandLCD; break; case Panel_800x600: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1024x768: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, 0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1280x720: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, 0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); if(SiS_Pr->PanelHT == 1650) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; } case Panel_1280x768_2: { /* LVDS only */ static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); switch(resinfo) { case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; } break; } case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */ static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1280x800_2: { /* SiS LVDS */ static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); switch(resinfo) { case SIS_RI_1280x720: case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; } break; } case Panel_1280x854: { /* SiS LVDS */ static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); switch(resinfo) { case SIS_RI_1280x720: case SIS_RI_1280x768: case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; } break; } case Panel_1280x960: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, SIS_RI_1280x854,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1280x1024: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, SIS_RI_1280x854,SIS_RI_1280x960,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1400x1050: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854, SIS_RI_1280x960,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); switch(resinfo) { case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) { SiS_Pr->SiS_LCDInfo |= DontExpandLCD; } break; case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD; break; } break; } case Panel_1600x1200: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } case Panel_1680x1050: { static const unsigned char nonscalingmodes[] = { SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768, SIS_RI_1360x1024,0xff }; SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); break; } } } #ifdef CONFIG_FB_SIS_300 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) { SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */ } } if(SiS_Pr->ChipType < SIS_315H) { if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { if(SiS_Pr->SiS_UseROM) { if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { if(!(ROMAddr[0x235] & 0x02)) { SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD); } } } } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) { SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD); } } } #endif /* Special cases */ if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) { SiS_Pr->SiS_LCDInfo &= ~LCDPass11; } if(SiS_Pr->SiS_IF_DEF_TRUMPION) { SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11); } switch(SiS_Pr->SiS_LCDResInfo) { case Panel_640x480: SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11); break; case Panel_1280x800: /* Don't pass 1:1 by default (TMDS special) */ if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11; break; case Panel_1280x960: SiS_Pr->SiS_LCDInfo &= ~LCDPass11; break; case Panel_Custom: if((!SiS_Pr->CP_PrefClock) || (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->Pan