📄 init301.c
字号:
/* $XFree86$ *//* $XdotOrg$ *//* * Mode initializing code (CRT2 section) * for SiS 300/305/540/630/730 and * SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760 * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x) * * Copyright (C) 2001-2004 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 EXPRESSED 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 <thomas@winischhofer.net> * * Formerly based on non-functional code-fragements for 300 series by SiS, Inc. * Used by permission. * * TW says: This code looks awful, I know. But please don't do anything about * this otherwise debugging will be hell. * The code is extremely fragile as regards the different chipsets, different * video bridges and combinations thereof. If anything is changed, extreme * care has to be taken that that change doesn't break it for other chipsets, * bridges or combinations thereof. * All comments in this file are by me, regardless if marked TW or not. * */#if 1#define SET_EMI /* 302LV/ELV: Set EMI values */#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 SIS300#include "oem300.h"#endif#ifdef SIS315H#include "oem310.h"#endif#define SiS_I2CDELAY 1000#define SiS_I2CDELAYSHORT 150static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);/*********************************************//* HELPER: Lock/Unlock CRT2 *//*********************************************/voidSiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ if(HwInfo->jChipType >= SIS_315H) SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01); else SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);}voidSiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ if(HwInfo->jChipType >= SIS_315H) SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE); else SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);}/*********************************************//* HELPER: Write SR11 *//*********************************************/static voidSiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR){ if(HwInfo->jChipType >= SIS_661) { DataAND &= 0x0f; DataOR &= 0x0f; } SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);}/*********************************************//* HELPER: Get Pointer to LCD structure *//*********************************************/#ifdef SIS315Hstatic UCHAR *GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; UCHAR *myptr = NULL; USHORT romindex = 0; /* Use the BIOS tables only for LVDS panels; DVI is unreliable * due to the variaty of panels the BIOS doesn't know about. */ if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { myptr = (UCHAR *)SiS_LCDStruct661; romindex = SISGETROMW(0x100); if(romindex) { romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26); myptr = &ROMAddr[romindex]; } } return myptr;}static USHORTGetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; USHORT romptr = 0; /* Use the BIOS tables only for LVDS panels; DVI is unreliable * due to the variaty of panels the BIOS doesn't know about. */ if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { romptr = SISGETROMW(0x102); romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize); } return(romptr);}#endif/*********************************************//* Adjust Rate for CRT2 *//*********************************************/static BOOLEANSiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, USHORT *i, PSIS_HW_INFO HwInfo){ USHORT checkmask=0,modeid,infoflag; modeid = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID; if(SiS_Pr->SiS_VBType & VB_SISVB) { if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { checkmask |= SupportRAMDAC2; if(HwInfo->jChipType >= SIS_315H) { checkmask |= SupportRAMDAC2_135; if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { checkmask |= SupportRAMDAC2_162; if(SiS_Pr->SiS_VBType & VB_SIS301C) { checkmask |= SupportRAMDAC2_202; } } } } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { checkmask |= SupportLCD; if(HwInfo->jChipType >= 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_SIS301BLV302BLV) { 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[RefreshRateTableIndex+(*i)].ModeID == modeid; (*i)--) { infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*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[RefreshRateTableIndex + (*i)].ModeID != modeid) { return FALSE; } infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag; if(infoflag & checkmask) return TRUE; } return TRUE;}/*********************************************//* Get rate index *//*********************************************/USHORTSiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo){ SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }; USHORT RefreshRateTableIndex,i,backup_i; USHORT modeflag,index,temp,backupindex; /* 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; } } } RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; ModeNo = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID; if(HwInfo->jChipType >= 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) RefreshRateTableIndex++; } } } i = 0; do { if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + i].ModeID != ModeNo) break; temp = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag; temp &= ModeInfoFlag; 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[RefreshRateTableIndex + 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, RefreshRateTableIndex, &i, HwInfo))) { i = backup_i; } } return(RefreshRateTableIndex + i);}/*********************************************//* STORE CRT2 INFO in CR34 *//*********************************************/static voidSiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo){ USHORT 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 SIS300static BOOLEANSiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase; USHORT temp,temp1; if(SiS_Pr->SiS_UseROM) { if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4); temp1 = SISGETROMW(0x23b); if(temp1 & temp) return TRUE; } } return FALSE;}static BOOLEANSiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo){ UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase; USHORT temp,temp1; if(SiS_Pr->SiS_UseROM) { if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4); temp1 = SISGETROMW(0x23d); if(temp1 & temp) return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -