brintos

brintos / linux-shallow public Read only

0
0
Text · 104.9 KiB · 2ba91d6 Raw
3632 lines · c
1/* $XFree86$ */2/* $XdotOrg$ */3/*4 * Mode initializing code (CRT1 section) for5 * for SiS 300/305/540/630/730,6 *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],7 *     XGI Volari V3XT/V5/V8, Z78 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)9 *10 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria11 *12 * If distributed as part of the Linux kernel, the following license terms13 * apply:14 *15 * * This program is free software; you can redistribute it and/or modify16 * * it under the terms of the GNU General Public License as published by17 * * the Free Software Foundation; either version 2 of the named License,18 * * or any later version.19 * *20 * * This program is distributed in the hope that it will be useful,21 * * but WITHOUT ANY WARRANTY; without even the implied warranty of22 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the23 * * GNU General Public License for more details.24 * *25 * * You should have received a copy of the GNU General Public License26 * * along with this program; if not, write to the Free Software27 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA28 *29 * Otherwise, the following license terms apply:30 *31 * * Redistribution and use in source and binary forms, with or without32 * * modification, are permitted provided that the following conditions33 * * are met:34 * * 1) Redistributions of source code must retain the above copyright35 * *    notice, this list of conditions and the following disclaimer.36 * * 2) Redistributions in binary form must reproduce the above copyright37 * *    notice, this list of conditions and the following disclaimer in the38 * *    documentation and/or other materials provided with the distribution.39 * * 3) The name of the author may not be used to endorse or promote products40 * *    derived from this software without specific prior written permission.41 * *42 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR43 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES44 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.45 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,46 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT47 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,48 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY49 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT50 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF51 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.52 *53 * Author: 	Thomas Winischhofer <thomas@winischhofer.net>54 *55 * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.56 * Used by permission.57 */58 59#include "init.h"60 61#ifdef CONFIG_FB_SIS_30062#include "300vtbl.h"63#endif64 65#ifdef CONFIG_FB_SIS_31566#include "310vtbl.h"67#endif68 69#if defined(ALLOC_PRAGMA)70#pragma alloc_text(PAGE,SiSSetMode)71#endif72 73/*********************************************/74/*         POINTER INITIALIZATION            */75/*********************************************/76 77#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)78static void79InitCommonPointer(struct SiS_Private *SiS_Pr)80{81   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;82   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;83   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;84   SiS_Pr->SiS_StandTable    = SiS_StandTable;85 86   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;87   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;88   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;89   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;90 91   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;92   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;93   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;94#if 095   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;96   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;97#endif98 99   SiS_Pr->SiS_StPALData   = SiS_StPALData;100   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;101   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;102   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;103   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;104   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;105   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;106   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;107   SiS_Pr->SiS_St525pData  = SiS_St525pData;108   SiS_Pr->SiS_St750pData  = SiS_St750pData;109   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;110   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;111   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;112 113   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;114   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;115 116   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;117   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;118   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;119   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;120   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;121   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;122   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;123   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;124   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;125   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;126   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;127   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;128   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;129 130   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;131   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;132   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;133   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;134   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;135   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;136 137   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;138   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;139   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;140   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;141   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;142   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;143   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;144#if 0145   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;146   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;147   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;148   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;149#endif150 151   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;152   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;153 154   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */155   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */156}157#endif158 159#ifdef CONFIG_FB_SIS_300160static void161InitTo300Pointer(struct SiS_Private *SiS_Pr)162{163   InitCommonPointer(SiS_Pr);164 165   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;166   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;167   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;168   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;169   if(SiS_Pr->ChipType == SIS_300) {170      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */171   } else {172      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */173   }174   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;175   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;176 177   SiS_Pr->SiS_SR15  = SiS300_SR15;178 179   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;180   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;181 182   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;183   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;184   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;185   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;186 187   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;188   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;189   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;190 191   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;192   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;193   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */194   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */195   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */196   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */197   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;198 199   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;200   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;201   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;202   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;203   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;204 205   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;206   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;207   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;208   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;209 210   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;211   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;212   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;213   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;214   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;215   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;216   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;217   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;218   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;219   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */220   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */221   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */222   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */223   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;224   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;225   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;226   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;227   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;228   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */229   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */230   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */231   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */232   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;233}234#endif235 236#ifdef CONFIG_FB_SIS_315237static void238InitTo310Pointer(struct SiS_Private *SiS_Pr)239{240   InitCommonPointer(SiS_Pr);241 242   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;243   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;244   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;245   if(SiS_Pr->ChipType >= SIS_340) {246      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */247   } else if(SiS_Pr->ChipType >= SIS_761) {248      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */249   } else if(SiS_Pr->ChipType >= SIS_760) {250      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */251   } else if(SiS_Pr->ChipType >= SIS_661) {252      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */253   } else if(SiS_Pr->ChipType == SIS_330) {254      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */255   } else if(SiS_Pr->ChipType > SIS_315PRO) {256      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */257   } else {258      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */259   }260   if(SiS_Pr->ChipType >= SIS_340) {261      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;262   } else {263      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;264   }265   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;266   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;267 268   SiS_Pr->SiS_SR15  = SiS310_SR15;269 270   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;271   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;272 273   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;274   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;275   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;276   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;277 278   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;279 280   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;281   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;282   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;283   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;284   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;285   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;286   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;287 288   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;289   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;290   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;291   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;292   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;293 294   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;295   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;296   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;297   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;298   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;299   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;300   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;301   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;302   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;303 304   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;305   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;306   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;307   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;308   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;309   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;310   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;311   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;312   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;313}314#endif315 316bool317SiSInitPtr(struct SiS_Private *SiS_Pr)318{319   if(SiS_Pr->ChipType < SIS_315H) {320#ifdef CONFIG_FB_SIS_300321      InitTo300Pointer(SiS_Pr);322#else323      return false;324#endif325   } else {326#ifdef CONFIG_FB_SIS_315327      InitTo310Pointer(SiS_Pr);328#else329      return false;330#endif331   }332   return true;333}334 335/*********************************************/336/*            HELPER: Get ModeID             */337/*********************************************/338 339static340unsigned short341SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,342		int Depth, bool FSTN, int LCDwidth, int LCDheight)343{344   unsigned short ModeIndex = 0;345 346   switch(HDisplay)347   {348	case 320:349		if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];350		else if(VDisplay == 240) {351			if((VBFlags & CRT2_LCD) && (FSTN))352				ModeIndex = ModeIndex_320x240_FSTN[Depth];353			else354				ModeIndex = ModeIndex_320x240[Depth];355		}356		break;357	case 400:358		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDheight >= 600))) {359			if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];360		}361		break;362	case 512:363		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDheight >= 768))) {364			if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];365		}366		break;367	case 640:368		if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];369		else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];370		break;371	case 720:372		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];373		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];374		break;375	case 768:376		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];377		break;378	case 800:379		if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];380		else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];381		break;382	case 848:383		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];384		break;385	case 856:386		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];387		break;388	case 960:389		if(VGAEngine == SIS_315_VGA) {390			if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];391			else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];392		}393		break;394	case 1024:395		if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];396		else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];397		else if(VGAEngine == SIS_300_VGA) {398			if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];399		}400		break;401	case 1152:402		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];403		if(VGAEngine == SIS_300_VGA) {404			if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];405		}406		break;407	case 1280:408		switch(VDisplay) {409			case 720:410				ModeIndex = ModeIndex_1280x720[Depth];411				break;412			case 768:413				if(VGAEngine == SIS_300_VGA) {414					ModeIndex = ModeIndex_300_1280x768[Depth];415				} else {416					ModeIndex = ModeIndex_310_1280x768[Depth];417				}418				break;419			case 800:420				if(VGAEngine == SIS_315_VGA) {421					ModeIndex = ModeIndex_1280x800[Depth];422				}423				break;424			case 854:425				if(VGAEngine == SIS_315_VGA) {426					ModeIndex = ModeIndex_1280x854[Depth];427				}428				break;429			case 960:430				ModeIndex = ModeIndex_1280x960[Depth];431				break;432			case 1024:433				ModeIndex = ModeIndex_1280x1024[Depth];434				break;435		}436		break;437	case 1360:438		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];439		if(VGAEngine == SIS_300_VGA) {440			if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];441		}442		break;443	case 1400:444		if(VGAEngine == SIS_315_VGA) {445			if(VDisplay == 1050) {446				ModeIndex = ModeIndex_1400x1050[Depth];447			}448		}449		break;450	case 1600:451		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];452		break;453	case 1680:454		if(VGAEngine == SIS_315_VGA) {455			if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];456		}457		break;458	case 1920:459		if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];460		else if(VGAEngine == SIS_315_VGA) {461			if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];462		}463		break;464	case 2048:465		if(VDisplay == 1536) {466			if(VGAEngine == SIS_300_VGA) {467				ModeIndex = ModeIndex_300_2048x1536[Depth];468			} else {469				ModeIndex = ModeIndex_310_2048x1536[Depth];470			}471		}472		break;473   }474 475   return ModeIndex;476}477 478unsigned short479SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,480		int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,481		unsigned int VBFlags2)482{483   unsigned short ModeIndex = 0;484 485   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {486 487      switch(HDisplay)488      {489	case 320:490	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {491		if(VDisplay == 200) {492		   if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];493		} else if(VDisplay == 240) {494		   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];495		   else if(VGAEngine == SIS_315_VGA) {496		      ModeIndex = ModeIndex_320x240_FSTN[Depth];497		   }498		}499	     }500	     break;501	case 400:502	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {503		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {504		   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];505		}506	     }507	     break;508	case 512:509	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {510		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {511		   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {512		      if(VDisplay == 384) {513		         ModeIndex = ModeIndex_512x384[Depth];514		      }515		   }516		}517	     }518	     break;519	case 640:520	     if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];521	     else if(VDisplay == 400) {522		if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))523		   ModeIndex = ModeIndex_640x400[Depth];524	     }525	     break;526	case 800:527	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];528	     break;529	case 848:530	     if(CustomT == CUT_PANEL848) {531	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];532	     }533	     break;534	case 856:535	     if(CustomT == CUT_PANEL856) {536	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];537	     }538	     break;539	case 1024:540	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];541	     else if(VGAEngine == SIS_300_VGA) {542		if((VDisplay == 600) && (LCDheight == 600)) {543		   ModeIndex = ModeIndex_1024x600[Depth];544		}545	     }546	     break;547	case 1152:548	     if(VGAEngine == SIS_300_VGA) {549		if((VDisplay == 768) && (LCDheight == 768)) {550		   ModeIndex = ModeIndex_1152x768[Depth];551		}552	     }553	     break;554        case 1280:555	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];556	     else if(VGAEngine == SIS_315_VGA) {557		if((VDisplay == 768) && (LCDheight == 768)) {558		   ModeIndex = ModeIndex_310_1280x768[Depth];559		}560	     }561	     break;562	case 1360:563	     if(VGAEngine == SIS_300_VGA) {564		if(CustomT == CUT_BARCO1366) {565		   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];566		}567	     }568	     if(CustomT == CUT_PANEL848) {569		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];570	     }571	     break;572	case 1400:573	     if(VGAEngine == SIS_315_VGA) {574		if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];575	     }576	     break;577	case 1600:578	     if(VGAEngine == SIS_315_VGA) {579		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];580	     }581	     break;582      }583 584   } else if(VBFlags2 & VB2_SISBRIDGE) {585 586      switch(HDisplay)587      {588	case 320:589	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];590	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];591	     break;592	case 400:593	     if(LCDwidth >= 800 && LCDheight >= 600) {594		if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];595	     }596	     break;597	case 512:598	     if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {599		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];600	     }601	     break;602	case 640:603	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];604	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];605	     break;606	case 720:607	     if(VGAEngine == SIS_315_VGA) {608		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];609		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];610	     }611	     break;612	case 768:613	     if(VGAEngine == SIS_315_VGA) {614		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];615	     }616	     break;617	case 800:618	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];619	     if(VGAEngine == SIS_315_VGA) {620		if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];621	     }622	     break;623	case 848:624	     if(VGAEngine == SIS_315_VGA) {625		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];626	     }627	     break;628	case 856:629	     if(VGAEngine == SIS_315_VGA) {630		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];631	     }632	     break;633	case 960:634	     if(VGAEngine == SIS_315_VGA) {635		if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];636		else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];637	     }638	     break;639	case 1024:640	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];641	     if(VGAEngine == SIS_315_VGA) {642		if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];643	     }644	     break;645	case 1152:646	     if(VGAEngine == SIS_315_VGA) {647		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];648	     }649	     break;650	case 1280:651	     switch(VDisplay) {652	     case 720:653		ModeIndex = ModeIndex_1280x720[Depth];654		break;655	     case 768:656		if(VGAEngine == SIS_300_VGA) {657		   ModeIndex = ModeIndex_300_1280x768[Depth];658		} else {659		   ModeIndex = ModeIndex_310_1280x768[Depth];660		}661		break;662	     case 800:663		if(VGAEngine == SIS_315_VGA) {664		   ModeIndex = ModeIndex_1280x800[Depth];665		}666		break;667	     case 854:668		if(VGAEngine == SIS_315_VGA) {669		   ModeIndex = ModeIndex_1280x854[Depth];670		}671		break;672	     case 960:673		ModeIndex = ModeIndex_1280x960[Depth];674		break;675	     case 1024:676		ModeIndex = ModeIndex_1280x1024[Depth];677		break;678	     }679	     break;680	case 1360:681	     if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */682		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];683	     }684	     break;685	case 1400:686	     if(VGAEngine == SIS_315_VGA) {687		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {688		   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];689		}690	     }691	     break;692	case 1600:693	     if(VGAEngine == SIS_315_VGA) {694		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {695		   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];696		}697	     }698	     break;699#ifndef VB_FORBID_CRT2LCD_OVER_1600700	case 1680:701	     if(VGAEngine == SIS_315_VGA) {702		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {703		   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];704		}705	     }706	     break;707	case 1920:708	     if(VGAEngine == SIS_315_VGA) {709		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {710		   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];711		}712	     }713	     break;714	case 2048:715	     if(VGAEngine == SIS_315_VGA) {716		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {717		   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];718		}719	     }720	     break;721#endif722      }723   }724 725   return ModeIndex;726}727 728unsigned short729SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,730			unsigned int VBFlags2)731{732   unsigned short ModeIndex = 0;733 734   if(VBFlags2 & VB2_CHRONTEL) {735 736      switch(HDisplay)737      {738	case 512:739	     if(VGAEngine == SIS_315_VGA) {740		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];741	     }742	     break;743	case 640:744	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];745	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];746	     break;747	case 800:748	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];749	     break;750	case 1024:751	     if(VGAEngine == SIS_315_VGA) {752		if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];753	     }754	     break;755      }756 757   } else if(VBFlags2 & VB2_SISTVBRIDGE) {758 759      switch(HDisplay)760      {761	case 320:762	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];763	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];764	     break;765	case 400:766	     if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];767	     break;768	case 512:769	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||770		 (VBFlags & TV_HIVISION) 					      ||771		 ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {772		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];773	     }774	     break;775	case 640:776	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];777	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];778	     break;779	case 720:780	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {781		if(VDisplay == 480) {782		   ModeIndex = ModeIndex_720x480[Depth];783		} else if(VDisplay == 576) {784		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||785		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )786		      ModeIndex = ModeIndex_720x576[Depth];787		}788	     }789             break;790	case 768:791	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {792		if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||793		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {794		   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];795		}796             }797	     break;798	case 800:799	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];800	     else if(VDisplay == 480) {801		if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {802		   ModeIndex = ModeIndex_800x480[Depth];803		}804	     }805	     break;806	case 960:807	     if(VGAEngine == SIS_315_VGA) {808		if(VDisplay == 600) {809		   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {810		      ModeIndex = ModeIndex_960x600[Depth];811		   }812		}813	     }814	     break;815	case 1024:816	     if(VDisplay == 768) {817		if(VBFlags2 & VB2_30xBLV) {818		   ModeIndex = ModeIndex_1024x768[Depth];819		}820	     } else if(VDisplay == 576) {821		if( (VBFlags & TV_HIVISION) ||822		    ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||823		    ((VBFlags2 & VB2_30xBLV) &&824		     ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {825		   ModeIndex = ModeIndex_1024x576[Depth];826		}827	     }828	     break;829	case 1280:830	     if(VDisplay == 720) {831		if((VBFlags & TV_HIVISION) ||832		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {833		   ModeIndex = ModeIndex_1280x720[Depth];834		}835	     } else if(VDisplay == 1024) {836		if((VBFlags & TV_HIVISION) ||837		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {838		   ModeIndex = ModeIndex_1280x1024[Depth];839		}840	     }841	     break;842      }843   }844   return ModeIndex;845}846 847unsigned short848SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,849			unsigned int VBFlags2)850{851   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;852 853   if(HDisplay >= 1920) return 0;854 855   switch(HDisplay)856   {857	case 1600:858		if(VDisplay == 1200) {859			if(VGAEngine != SIS_315_VGA) return 0;860			if(!(VBFlags2 & VB2_30xB)) return 0;861		}862		break;863	case 1680:864		if(VDisplay == 1050) {865			if(VGAEngine != SIS_315_VGA) return 0;866			if(!(VBFlags2 & VB2_30xB)) return 0;867		}868		break;869   }870 871   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);872}873 874 875/*********************************************/876/*          HELPER: SetReg, GetReg           */877/*********************************************/878 879void880SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)881{882	outb(index, port);883	outb(data, port + 1);884}885 886void887SiS_SetRegByte(SISIOADDRESS port, u8 data)888{889	outb(data, port);890}891 892void893SiS_SetRegShort(SISIOADDRESS port, u16 data)894{895	outw(data, port);896}897 898void899SiS_SetRegLong(SISIOADDRESS port, u32 data)900{901	outl(data, port);902}903 904u8905SiS_GetReg(SISIOADDRESS port, u8 index)906{907	outb(index, port);908	return inb(port + 1);909}910 911u8912SiS_GetRegByte(SISIOADDRESS port)913{914	return inb(port);915}916 917u16918SiS_GetRegShort(SISIOADDRESS port)919{920	return inw(port);921}922 923u32924SiS_GetRegLong(SISIOADDRESS port)925{926	return inl(port);927}928 929void930SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)931{932   u8 temp;933 934   temp = SiS_GetReg(Port, Index);935   temp = (temp & (DataAND)) | DataOR;936   SiS_SetReg(Port, Index, temp);937}938 939void940SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)941{942   u8 temp;943 944   temp = SiS_GetReg(Port, Index);945   temp &= DataAND;946   SiS_SetReg(Port, Index, temp);947}948 949void950SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)951{952   u8 temp;953 954   temp = SiS_GetReg(Port, Index);955   temp |= DataOR;956   SiS_SetReg(Port, Index, temp);957}958 959/*********************************************/960/*      HELPER: DisplayOn, DisplayOff        */961/*********************************************/962 963void964SiS_DisplayOn(struct SiS_Private *SiS_Pr)965{966   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);967}968 969void970SiS_DisplayOff(struct SiS_Private *SiS_Pr)971{972   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);973}974 975 976/*********************************************/977/*        HELPER: Init Port Addresses        */978/*********************************************/979 980void981SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)982{983   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;984   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;985   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;986   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;987   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;988   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;989   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;990   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;991   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;992   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;993   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;994   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;995   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;996   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;997   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;998   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;999   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;1000   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;1001   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;1002   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;1003   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;1004   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;1005}1006 1007/*********************************************/1008/*             HELPER: GetSysFlags           */1009/*********************************************/1010 1011static void1012SiS_GetSysFlags(struct SiS_Private *SiS_Pr)1013{1014   unsigned char cr5f, temp1, temp2;1015 1016   /* 661 and newer: NEVER write non-zero to SR11[7:4] */1017   /* (SR11 is used for DDC and in enable/disablebridge) */1018   SiS_Pr->SiS_SensibleSR11 = false;1019   SiS_Pr->SiS_MyCR63 = 0x63;1020   if(SiS_Pr->ChipType >= SIS_330) {1021      SiS_Pr->SiS_MyCR63 = 0x53;1022      if(SiS_Pr->ChipType >= SIS_661) {1023         SiS_Pr->SiS_SensibleSR11 = true;1024      }1025   }1026 1027   /* You should use the macros, not these flags directly */1028 1029   SiS_Pr->SiS_SysFlags = 0;1030   if(SiS_Pr->ChipType == SIS_650) {1031      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;1032      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);1033      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;1034      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);1035      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;1036      if((!temp1) || (temp2)) {1037	 switch(cr5f) {1038	    case 0x80:1039	    case 0x90:1040	    case 0xc0:1041	       SiS_Pr->SiS_SysFlags |= SF_IsM650;1042	       break;1043	    case 0xa0:1044	    case 0xb0:1045	    case 0xe0:1046	       SiS_Pr->SiS_SysFlags |= SF_Is651;1047	       break;1048	 }1049      } else {1050	 switch(cr5f) {1051	    case 0x90:1052	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;1053	       switch(temp1) {1054		  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;1055		  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;1056		  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;1057	       }1058	       break;1059	    case 0xb0:1060	       SiS_Pr->SiS_SysFlags |= SF_Is652;1061	       break;1062	    default:1063	       SiS_Pr->SiS_SysFlags |= SF_IsM650;1064	       break;1065	 }1066      }1067   }1068 1069   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {1070      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {1071         SiS_Pr->SiS_SysFlags |= SF_760LFB;1072      }1073      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {1074         SiS_Pr->SiS_SysFlags |= SF_760UMA;1075      }1076   }1077}1078 1079/*********************************************/1080/*         HELPER: Init PCI & Engines        */1081/*********************************************/1082 1083static void1084SiSInitPCIetc(struct SiS_Private *SiS_Pr)1085{1086   switch(SiS_Pr->ChipType) {1087#ifdef CONFIG_FB_SIS_3001088   case SIS_300:1089   case SIS_540:1090   case SIS_630:1091   case SIS_730:1092      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)1093       *     - RELOCATED VGA IO ENABLED (0x20)1094       *     - MMIO ENABLED (0x01)1095       * Leave other bits untouched.1096       */1097      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);1098      /*  - Enable 2D (0x40)1099       *  - Enable 3D (0x02)1100       *  - Enable 3D Vertex command fetch (0x10) ?1101       *  - Enable 3D command parser (0x08) ?1102       */1103      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);1104      break;1105#endif1106#ifdef CONFIG_FB_SIS_3151107   case SIS_315H:1108   case SIS_315:1109   case SIS_315PRO:1110   case SIS_650:1111   case SIS_740:1112   case SIS_330:1113   case SIS_661:1114   case SIS_741:1115   case SIS_660:1116   case SIS_760:1117   case SIS_761:1118   case SIS_340:1119   case XGI_40:1120      /* See above */1121      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);1122      /*  - Enable 3D G/L transformation engine (0x80)1123       *  - Enable 2D (0x40)1124       *  - Enable 3D vertex command fetch (0x10)1125       *  - Enable 3D command parser (0x08)1126       *  - Enable 3D (0x02)1127       */1128      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);1129      break;1130   case XGI_20:1131   case SIS_550:1132      /* See above */1133      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);1134      /* No 3D engine ! */1135      /*  - Enable 2D (0x40)1136       *  - disable 3D1137       */1138      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);1139      break;1140#endif1141   default:1142      break;1143   }1144}1145 1146/*********************************************/1147/*             HELPER: SetLVDSetc            */1148/*********************************************/1149 1150static1151void1152SiSSetLVDSetc(struct SiS_Private *SiS_Pr)1153{1154   unsigned short temp;1155 1156   SiS_Pr->SiS_IF_DEF_LVDS = 0;1157   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;1158   SiS_Pr->SiS_IF_DEF_CH70xx = 0;1159   SiS_Pr->SiS_IF_DEF_CONEX = 0;1160 1161   SiS_Pr->SiS_ChrontelInit = 0;1162 1163   if(SiS_Pr->ChipType == XGI_20) return;1164 1165   /* Check for SiS30x first */1166   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);1167   if((temp == 1) || (temp == 2)) return;1168 1169   switch(SiS_Pr->ChipType) {1170#ifdef CONFIG_FB_SIS_3001171   case SIS_540:1172   case SIS_630:1173   case SIS_730:1174	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;1175	if((temp >= 2) && (temp <= 5))	SiS_Pr->SiS_IF_DEF_LVDS = 1;1176	if(temp == 3)			SiS_Pr->SiS_IF_DEF_TRUMPION = 1;1177	if((temp == 4) || (temp == 5)) {1178		/* Save power status (and error check) - UNUSED */1179		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);1180		SiS_Pr->SiS_IF_DEF_CH70xx = 1;1181	}1182	break;1183#endif1184#ifdef CONFIG_FB_SIS_3151185   case SIS_550:1186   case SIS_650:1187   case SIS_740:1188   case SIS_330:1189	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;1190	if((temp >= 2) && (temp <= 3))	SiS_Pr->SiS_IF_DEF_LVDS = 1;1191	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;1192	break;1193   case SIS_661:1194   case SIS_741:1195   case SIS_660:1196   case SIS_760:1197   case SIS_761:1198   case SIS_340:1199   case XGI_20:1200   case XGI_40:1201	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;1202	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;1203	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;1204	if(temp == 4)			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */1205	break;1206#endif1207   default:1208	break;1209   }1210}1211 1212/*********************************************/1213/*          HELPER: Enable DSTN/FSTN         */1214/*********************************************/1215 1216void1217SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)1218{1219   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;1220}1221 1222void1223SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)1224{1225   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;1226}1227 1228/*********************************************/1229/*            HELPER: Get modeflag           */1230/*********************************************/1231 1232unsigned short1233SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,1234		unsigned short ModeIdIndex)1235{1236   if(SiS_Pr->UseCustomMode) {1237      return SiS_Pr->CModeFlag;1238   } else if(ModeNo <= 0x13) {1239      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;1240   } else {1241      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;1242   }1243}1244 1245/*********************************************/1246/*        HELPER: Determine ROM usage        */1247/*********************************************/1248 1249bool1250SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)1251{1252   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;1253   unsigned short romversoffs, romvmaj = 1, romvmin = 0;1254 1255   if(SiS_Pr->ChipType >= XGI_20) {1256      /* XGI ROMs don't qualify */1257      return false;1258   } else if(SiS_Pr->ChipType >= SIS_761) {1259      /* I very much assume 761, 340 and newer will use new layout */1260      return true;1261   } else if(SiS_Pr->ChipType >= SIS_661) {1262      if((ROMAddr[0x1a] == 'N') &&1263	 (ROMAddr[0x1b] == 'e') &&1264	 (ROMAddr[0x1c] == 'w') &&1265	 (ROMAddr[0x1d] == 'V')) {1266	 return true;1267      }1268      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);1269      if(romversoffs) {1270	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {1271	    romvmaj = ROMAddr[romversoffs] - '0';1272	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');1273	 }1274      }1275      if((romvmaj != 0) || (romvmin >= 92)) {1276	 return true;1277      }1278   } else if(IS_SIS650740) {1279      if((ROMAddr[0x1a] == 'N') &&1280	 (ROMAddr[0x1b] == 'e') &&1281	 (ROMAddr[0x1c] == 'w') &&1282	 (ROMAddr[0x1d] == 'V')) {1283	 return true;1284      }1285   }1286   return false;1287}1288 1289static void1290SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)1291{1292   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;1293   unsigned short romptr = 0;1294 1295   SiS_Pr->SiS_UseROM = false;1296   SiS_Pr->SiS_ROMNew = false;1297   SiS_Pr->SiS_PWDOffset = 0;1298 1299   if(SiS_Pr->ChipType >= XGI_20) return;1300 1301   if((ROMAddr) && (SiS_Pr->UseROM)) {1302      if(SiS_Pr->ChipType == SIS_300) {1303	 /* 300: We check if the code starts below 0x220 by1304	  * checking the jmp instruction at the beginning1305	  * of the BIOS image.1306	  */1307	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)1308	    SiS_Pr->SiS_UseROM = true;1309      } else if(SiS_Pr->ChipType < SIS_315H) {1310	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps1311	  * the others do as well1312	  */1313	 SiS_Pr->SiS_UseROM = true;1314      } else {1315	 /* 315/330 series stick to the standard(s) */1316	 SiS_Pr->SiS_UseROM = true;1317	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {1318	    SiS_Pr->SiS_EMIOffset = 14;1319	    SiS_Pr->SiS_PWDOffset = 17;1320	    SiS_Pr->SiS661LCD2TableSize = 36;1321	    /* Find out about LCD data table entry size */1322	    if((romptr = SISGETROMW(0x0102))) {1323	       if(ROMAddr[romptr + (32 * 16)] == 0xff)1324		  SiS_Pr->SiS661LCD2TableSize = 32;1325	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)1326		  SiS_Pr->SiS661LCD2TableSize = 34;1327	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)	   /* 0.94, 2.05.00+ */1328		  SiS_Pr->SiS661LCD2TableSize = 36;1329	       else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */1330		 	(ROMAddr[0x6F] & 0x01) ) {		   /* 2.03.00 - <2.05.00 */1331		  SiS_Pr->SiS661LCD2TableSize = 38;		   /* UMC data layout abandoned at 2.05.00 */1332		  SiS_Pr->SiS_EMIOffset = 16;1333		  SiS_Pr->SiS_PWDOffset = 19;1334	       }1335	    }1336	 }1337      }1338   }1339}1340 1341/*********************************************/1342/*        HELPER: SET SEGMENT REGISTERS      */1343/*********************************************/1344 1345static void1346SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)1347{1348   unsigned short temp;1349 1350   value &= 0x00ff;1351   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;1352   temp |= (value >> 4);1353   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);1354   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;1355   temp |= (value & 0x0f);1356   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);1357}1358 1359static void1360SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)1361{1362   unsigned short temp;1363 1364   value &= 0x00ff;1365   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;1366   temp |= (value & 0xf0);1367   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);1368   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;1369   temp |= (value << 4);1370   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);1371}1372 1373static void1374SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)1375{1376   SiS_SetSegRegLower(SiS_Pr, value);1377   SiS_SetSegRegUpper(SiS_Pr, value);1378}1379 1380static void1381SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)1382{1383   SiS_SetSegmentReg(SiS_Pr, 0);1384}1385 1386static void1387SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)1388{1389   unsigned short temp = value >> 8;1390 1391   temp &= 0x07;1392   temp |= (temp << 4);1393   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);1394   SiS_SetSegmentReg(SiS_Pr, value);1395}1396 1397static void1398SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)1399{1400   SiS_SetSegmentRegOver(SiS_Pr, 0);1401}1402 1403static void1404SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)1405{1406   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {1407      SiS_ResetSegmentReg(SiS_Pr);1408      SiS_ResetSegmentRegOver(SiS_Pr);1409   }1410}1411 1412/*********************************************/1413/*             HELPER: GetVBType             */1414/*********************************************/1415 1416static1417void1418SiS_GetVBType(struct SiS_Private *SiS_Pr)1419{1420   unsigned short flag = 0, rev = 0, nolcd = 0;1421   unsigned short p4_0f, p4_25, p4_27;1422 1423   SiS_Pr->SiS_VBType = 0;1424 1425   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))1426      return;1427 1428   if(SiS_Pr->ChipType == XGI_20)1429      return;1430 1431   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);1432 1433   if(flag > 3)1434      return;1435 1436   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);1437 1438   if(flag >= 2) {1439      SiS_Pr->SiS_VBType = VB_SIS302B;1440   } else if(flag == 1) {1441      if(rev >= 0xC0) {1442	 SiS_Pr->SiS_VBType = VB_SIS301C;1443      } else if(rev >= 0xB0) {1444	 SiS_Pr->SiS_VBType = VB_SIS301B;1445	 /* Check if 30xB DH version (no LCD support, use Panel Link instead) */1446	 nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);1447	 if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;1448      } else {1449	 SiS_Pr->SiS_VBType = VB_SIS301;1450      }1451   }1452   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {1453      if(rev >= 0xE0) {1454	 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);1455	 if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;1456	 else 	 	  SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */1457      } else if(rev >= 0xD0) {1458	 SiS_Pr->SiS_VBType = VB_SIS301LV;1459      }1460   }1461   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {1462      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);1463      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);1464      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);1465      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);1466      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);1467      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);1468      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {1469         SiS_Pr->SiS_VBType |= VB_UMC;1470      }1471      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);1472      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);1473      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);1474   }1475}1476 1477/*********************************************/1478/*           HELPER: Check RAM size          */1479/*********************************************/1480 1481static bool1482SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,1483		unsigned short ModeIdIndex)1484{1485   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);1486   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);1487   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;1488 1489   if(!AdapterMemSize) return true;1490 1491   if(AdapterMemSize < memorysize) return false;1492   return true;1493}1494 1495/*********************************************/1496/*           HELPER: Get DRAM type           */1497/*********************************************/1498 1499#ifdef CONFIG_FB_SIS_3151500static unsigned char1501SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)1502{1503   unsigned char data;1504 1505   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {1506      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;1507   } else {1508      if(SiS_Pr->ChipType >= XGI_20) {1509         /* Do I need this? SR17 seems to be zero anyway... */1510	 data = 0;1511      } else if(SiS_Pr->ChipType >= SIS_340) {1512	 /* TODO */1513	 data = 0;1514      } else if(SiS_Pr->ChipType >= SIS_661) {1515	 if(SiS_Pr->SiS_ROMNew) {1516	    data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);1517	 } else {1518	    data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;1519	 }1520      } else if(IS_SIS550650740) {1521	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;1522      } else {	/* 315, 330 */1523	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;1524	 if(SiS_Pr->ChipType == SIS_330) {1525	    if(data > 1) {1526	       switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {1527	       case 0x00: data = 1; break;1528	       case 0x10: data = 3; break;1529	       case 0x20: data = 3; break;1530	       case 0x30: data = 2; break;1531	       }1532	    } else {1533	       data = 0;1534	    }1535	 }1536      }1537   }1538 1539   return data;1540}1541 1542static unsigned short1543SiS_GetMCLK(struct SiS_Private *SiS_Pr)1544{1545   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;1546   unsigned short index;1547 1548   index = SiS_Get310DRAMType(SiS_Pr);1549   if(SiS_Pr->ChipType >= SIS_661) {1550      if(SiS_Pr->SiS_ROMNew) {1551	 return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));1552      }1553      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);1554   } else if(index >= 4) {1555      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);1556   } else {1557      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);1558   }1559}1560#endif1561 1562/*********************************************/1563/*           HELPER: ClearBuffer             */1564/*********************************************/1565 1566static void1567SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)1568{1569   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;1570   unsigned int   memsize = SiS_Pr->VideoMemorySize;1571   unsigned short SISIOMEMTYPE *pBuffer;1572   int i;1573 1574   if(!memaddr || !memsize) return;1575 1576   if(SiS_Pr->SiS_ModeType >= ModeEGA) {1577      if(ModeNo > 0x13) {1578	 memset_io(memaddr, 0, memsize);1579      } else {1580	 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;1581	 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);1582      }1583   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {1584      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;1585      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);1586   } else {1587      memset_io(memaddr, 0, 0x8000);1588   }1589}1590 1591/*********************************************/1592/*           HELPER: SearchModeID            */1593/*********************************************/1594 1595bool1596SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,1597		unsigned short *ModeIdIndex)1598{1599   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;1600 1601   if((*ModeNo) <= 0x13) {1602 1603      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;1604 1605      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {1606	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;1607	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;1608      }1609 1610      if((*ModeNo) == 0x07) {1611	  if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */1612	  /* else 350 lines */1613      }1614      if((*ModeNo) <= 0x03) {1615	 if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;1616	 if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */1617	 /* else 350 lines  */1618      }1619      /* else 200 lines  */1620 1621   } else {1622 1623      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {1624	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;1625	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;1626      }1627 1628   }1629   return true;1630}1631 1632/*********************************************/1633/*            HELPER: GetModePtr             */1634/*********************************************/1635 1636unsigned short1637SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)1638{1639   unsigned short index;1640 1641   if(ModeNo <= 0x13) {1642      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;1643   } else {1644      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;1645      else index = 0x0F;1646   }1647   return index;1648}1649 1650/*********************************************/1651/*         HELPERS: Get some indices         */1652/*********************************************/1653 1654unsigned short1655SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)1656{1657   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {1658      if(UseWide == 1) {1659         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;1660      } else {1661         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;1662      }1663   } else {1664      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;1665   }1666}1667 1668unsigned short1669SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)1670{1671   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {1672      if(UseWide == 1) {1673         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;1674      } else {1675         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;1676      }1677   } else {1678      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;1679   }1680}1681 1682/*********************************************/1683/*           HELPER: LowModeTests            */1684/*********************************************/1685 1686static bool1687SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)1688{1689   unsigned short temp, temp1, temp2;1690 1691   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))1692      return true;1693   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);1694   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);1695   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);1696   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);1697   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);1698   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);1699   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);1700   if((SiS_Pr->ChipType >= SIS_315H) ||1701      (SiS_Pr->ChipType == SIS_300)) {1702      if(temp2 == 0x55) return false;1703      else return true;1704   } else {1705      if(temp2 != 0x55) return true;1706      else {1707	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);1708	 return false;1709      }1710   }1711}1712 1713static void1714SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)1715{1716   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {1717      SiS_Pr->SiS_SetFlag |= LowModeTests;1718   }1719}1720 1721/*********************************************/1722/*        HELPER: OPEN/CLOSE CRT1 CRTC       */1723/*********************************************/1724 1725static void1726SiS_OpenCRTC(struct SiS_Private *SiS_Pr)1727{1728   if(IS_SIS650) {1729      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);1730      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);1731      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);1732   } else if(IS_SIS661741660760) {1733      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);1734      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);1735      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);1736      if(!SiS_Pr->SiS_ROMNew) {1737	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);1738      }1739   }1740}1741 1742static void1743SiS_CloseCRTC(struct SiS_Private *SiS_Pr)1744{1745#if 0 /* This locks some CRTC registers. We don't want that. */1746   unsigned short temp1 = 0, temp2 = 0;1747 1748   if(IS_SIS661741660760) {1749      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {1750         temp1 = 0xa0; temp2 = 0x08;1751      }1752      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);1753      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);1754   }1755#endif1756}1757 1758static void1759SiS_HandleCRT1(struct SiS_Private *SiS_Pr)1760{1761   /* Enable CRT1 gating */1762   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);1763#if 01764   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {1765      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||1766         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {1767         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);1768      }1769   }1770#endif1771}1772 1773/*********************************************/1774/*           HELPER: GetColorDepth           */1775/*********************************************/1776 1777unsigned short1778SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,1779		unsigned short ModeIdIndex)1780{1781   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };1782   unsigned short modeflag;1783   short index;1784 1785   /* Do NOT check UseCustomMode, will skrew up FIFO */1786   if(ModeNo == 0xfe) {1787      modeflag = SiS_Pr->CModeFlag;1788   } else if(ModeNo <= 0x13) {1789      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;1790   } else {1791      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;1792   }1793 1794   index = (modeflag & ModeTypeMask) - ModeEGA;1795   if(index < 0) index = 0;1796   return ColorDepth[index];1797}1798 1799/*********************************************/1800/*             HELPER: GetOffset             */1801/*********************************************/1802 1803unsigned short1804SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,1805		unsigned short ModeIdIndex, unsigned short RRTI)1806{1807   unsigned short xres, temp, colordepth, infoflag;1808 1809   if(SiS_Pr->UseCustomMode) {1810      infoflag = SiS_Pr->CInfoFlag;1811      xres = SiS_Pr->CHDisplay;1812   } else {1813      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;1814      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;1815   }1816 1817   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);1818 1819   temp = xres / 16;1820   if(infoflag & InterlaceMode) temp <<= 1;1821   temp *= colordepth;1822   if(xres % 16) temp += (colordepth >> 1);1823 1824   return temp;1825}1826 1827/*********************************************/1828/*                   SEQ                     */1829/*********************************************/1830 1831static void1832SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)1833{1834   unsigned char SRdata;1835   int i;1836 1837   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);1838 1839   /* or "display off"  */1840   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;1841 1842   /* determine whether to force x8 dotclock */1843   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {1844 1845      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {1846         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;1847      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;1848 1849   }1850 1851   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);1852 1853   for(i = 2; i <= 4; i++) {1854      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];1855      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);1856   }1857}1858 1859/*********************************************/1860/*                  MISC                     */1861/*********************************************/1862 1863static void1864SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)1865{1866   unsigned char Miscdata;1867 1868   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;1869 1870   if(SiS_Pr->ChipType < SIS_661) {1871      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {1872	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {1873	   Miscdata |= 0x0C;1874	 }1875      }1876   }1877 1878   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);1879}1880 1881/*********************************************/1882/*                  CRTC                     */1883/*********************************************/1884 1885static void1886SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)1887{1888   unsigned char  CRTCdata;1889   unsigned short i;1890 1891   /* Unlock CRTC */1892   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);1893 1894   for(i = 0; i <= 0x18; i++) {1895      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];1896      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);1897   }1898 1899   if(SiS_Pr->ChipType >= SIS_661) {1900      SiS_OpenCRTC(SiS_Pr);1901      for(i = 0x13; i <= 0x14; i++) {1902	 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];1903	 SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);1904      }1905   } else if( ( (SiS_Pr->ChipType == SIS_630) ||1906	        (SiS_Pr->ChipType == SIS_730) )  &&1907	      (SiS_Pr->ChipRevision >= 0x30) ) {1908      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {1909	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {1910	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);1911	 }1912      }1913   }1914}1915 1916/*********************************************/1917/*                   ATT                     */1918/*********************************************/1919 1920static void1921SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)1922{1923   unsigned char  ARdata;1924   unsigned short i;1925 1926   for(i = 0; i <= 0x13; i++) {1927      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];1928 1929      if(i == 0x13) {1930	 /* Pixel shift. If screen on LCD or TV is shifted left or right,1931	  * this might be the cause.1932	  */1933	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {1934	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;1935	 }1936	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {1937	    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {1938	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {1939		  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;1940	       }1941	    }1942	 }1943	 if(SiS_Pr->ChipType >= SIS_661) {1944	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {1945	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;1946	    }1947	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {1948	    if(SiS_Pr->ChipType >= SIS_315H) {1949	       if(IS_SIS550650740660) {1950		  /* 315, 330 don't do this */1951		  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {1952		     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;1953		  } else {1954		     ARdata = 0;1955		  }1956	       }1957	    } else {1958	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;1959	    }1960	 }1961      }1962      SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */1963      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);	/* set index  */1964      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);	/* set data   */1965   }1966 1967   SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */1968   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);	/* set index  */1969   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);	/* set data   */1970 1971   SiS_GetRegByte(SiS_Pr->SiS_P3da);1972   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);	/* Enable Attribute  */1973   SiS_GetRegByte(SiS_Pr->SiS_P3da);1974}1975 1976/*********************************************/1977/*                   GRC                     */1978/*********************************************/1979 1980static void1981SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)1982{1983   unsigned char  GRdata;1984   unsigned short i;1985 1986   for(i = 0; i <= 0x08; i++) {1987      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];1988      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);1989   }1990 1991   if(SiS_Pr->SiS_ModeType > ModeVGA) {1992      /* 256 color disable */1993      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);1994   }1995}1996 1997/*********************************************/1998/*          CLEAR EXTENDED REGISTERS         */1999/*********************************************/2000 2001static void2002SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)2003{2004   unsigned short i;2005 2006   for(i = 0x0A; i <= 0x0E; i++) {2007      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);2008   }2009 2010   if(SiS_Pr->ChipType >= SIS_315H) {2011      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);2012      if(ModeNo <= 0x13) {2013	 if(ModeNo == 0x06 || ModeNo >= 0x0e) {2014	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);2015	 }2016      }2017   }2018}2019 2020/*********************************************/2021/*                 RESET VCLK                */2022/*********************************************/2023 2024static void2025SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)2026{2027   if(SiS_Pr->ChipType >= SIS_315H) {2028      if(SiS_Pr->ChipType < SIS_661) {2029	 if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;2030      }2031   } else {2032      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&2033	 (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {2034	 return;2035      }2036   }2037 2038   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);2039   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);2040   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);2041   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);2042   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);2043   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);2044   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);2045   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);2046}2047 2048/*********************************************/2049/*                  SYNC                     */2050/*********************************************/2051 2052static void2053SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)2054{2055   unsigned short sync;2056 2057   if(SiS_Pr->UseCustomMode) {2058      sync = SiS_Pr->CInfoFlag >> 8;2059   } else {2060      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;2061   }2062 2063   sync &= 0xC0;2064   sync |= 0x2f;2065   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);2066}2067 2068/*********************************************/2069/*                  CRTC/2                   */2070/*********************************************/2071 2072static void2073SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2074		unsigned short ModeIdIndex, unsigned short RRTI)2075{2076   unsigned short temp, i, j, modeflag;2077   unsigned char  *crt1data = NULL;2078 2079   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);2080 2081   if(SiS_Pr->UseCustomMode) {2082 2083      crt1data = &SiS_Pr->CCRT1CRTC[0];2084 2085   } else {2086 2087      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);2088 2089      /* Alternate for 1600x1200 LCDA */2090      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;2091 2092      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];2093 2094   }2095 2096   /* unlock cr0-7 */2097   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);2098 2099   for(i = 0, j = 0; i <= 7; i++, j++) {2100      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);2101   }2102   for(j = 0x10; i <= 10; i++, j++) {2103      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);2104   }2105   for(j = 0x15; i <= 12; i++, j++) {2106      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);2107   }2108   for(j = 0x0A; i <= 15; i++, j++) {2109      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);2110   }2111 2112   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);2113 2114   temp = (crt1data[16] & 0x01) << 5;2115   if(modeflag & DoubleScanMode) temp |= 0x80;2116   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);2117 2118   if(SiS_Pr->SiS_ModeType > ModeVGA) {2119      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);2120   }2121 2122#ifdef CONFIG_FB_SIS_3152123   if(SiS_Pr->ChipType == XGI_20) {2124      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);2125      if(!(temp = crt1data[5] & 0x1f)) {2126         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);2127      }2128      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));2129      temp = (crt1data[16] >> 5) + 3;2130      if(temp > 7) temp -= 7;2131      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));2132   }2133#endif2134}2135 2136/*********************************************/2137/*               OFFSET & PITCH              */2138/*********************************************/2139/*  (partly overruled by SetPitch() in XF86) */2140/*********************************************/2141 2142static void2143SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2144		unsigned short ModeIdIndex, unsigned short RRTI)2145{2146   unsigned short temp, DisplayUnit, infoflag;2147 2148   if(SiS_Pr->UseCustomMode) {2149      infoflag = SiS_Pr->CInfoFlag;2150   } else {2151      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;2152   }2153 2154   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);2155 2156   temp = (DisplayUnit >> 8) & 0x0f;2157   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);2158 2159   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);2160 2161   if(infoflag & InterlaceMode) DisplayUnit >>= 1;2162 2163   DisplayUnit <<= 5;2164   temp = (DisplayUnit >> 8) + 1;2165   if(DisplayUnit & 0xff) temp++;2166   if(SiS_Pr->ChipType == XGI_20) {2167      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;2168   }2169   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);2170}2171 2172/*********************************************/2173/*                  VCLK                     */2174/*********************************************/2175 2176static void2177SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2178		unsigned short ModeIdIndex, unsigned short RRTI)2179{2180   unsigned short index = 0, clka, clkb;2181 2182   if(SiS_Pr->UseCustomMode) {2183      clka = SiS_Pr->CSR2B;2184      clkb = SiS_Pr->CSR2C;2185   } else {2186      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);2187      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&2188	 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {2189	 /* Alternate for 1600x1200 LCDA */2190	 if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;2191	 clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;2192	 clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;2193      } else {2194	 clka = SiS_Pr->SiS_VCLKData[index].SR2B;2195	 clkb = SiS_Pr->SiS_VCLKData[index].SR2C;2196      }2197   }2198 2199   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);2200 2201   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);2202   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);2203 2204   if(SiS_Pr->ChipType >= SIS_315H) {2205#ifdef CONFIG_FB_SIS_3152206      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);2207      if(SiS_Pr->ChipType == XGI_20) {2208         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);2209	 if(mf & HalfDCLK) {2210	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));2211	    clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);2212	    clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);2213	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);2214	 }2215      }2216#endif2217   } else {2218      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);2219   }2220}2221 2222/*********************************************/2223/*                  FIFO                     */2224/*********************************************/2225 2226#ifdef CONFIG_FB_SIS_3002227void2228SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,2229		unsigned short *idx2)2230{2231   unsigned short temp1, temp2;2232   static const unsigned char ThTiming[8] = {2233		1, 2, 2, 3, 0, 1, 1, 22234   };2235 2236   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;2237   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);2238   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;2239   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));2240   (*idx1) <<= 1;2241}2242 2243static unsigned short2244SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)2245{2246   static const unsigned char ThLowA[8 * 3] = {2247		61, 3,52, 5,68, 7,100,11,2248		43, 3,42, 5,54, 7, 78,11,2249		34, 3,37, 5,47, 7, 67,112250   };2251 2252   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);2253}2254 2255unsigned short2256SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)2257{2258   static const unsigned char ThLowB[8 * 3] = {2259		81, 4,72, 6,88, 8,120,12,2260		55, 4,54, 6,66, 8, 90,12,2261		42, 4,45, 6,55, 8, 75,122262   };2263 2264   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);2265}2266 2267static unsigned short2268SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,2269		unsigned short colordepth, unsigned short key)2270{2271   unsigned short idx1, idx2;2272   unsigned int   longtemp = VCLK * colordepth;2273 2274   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);2275 2276   if(key == 0) {2277      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);2278   } else {2279      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);2280   }2281   idx1 = longtemp % (MCLK * 16);2282   longtemp /= (MCLK * 16);2283   if(idx1) longtemp++;2284   return (unsigned short)longtemp;2285}2286 2287static unsigned short2288SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,2289		unsigned short colordepth, unsigned short MCLK)2290{2291   unsigned short temp1, temp2;2292 2293   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);2294   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);2295   if(temp1 < 4) temp1 = 4;2296   temp1 -= 4;2297   if(temp2 < temp1) temp2 = temp1;2298   return temp2;2299}2300 2301static void2302SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2303		unsigned short RefreshRateTableIndex)2304{2305   unsigned short ThresholdLow = 0;2306   unsigned short temp, index, VCLK, MCLK, colorth;2307   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };2308 2309   if(ModeNo > 0x13) {2310 2311      /* Get VCLK  */2312      if(SiS_Pr->UseCustomMode) {2313	 VCLK = SiS_Pr->CSRClock;2314      } else {2315	 index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);2316	 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;2317      }2318 2319      /* Get half colordepth */2320      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];2321 2322      /* Get MCLK  */2323      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;2324      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;2325 2326      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;2327      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);2328 2329      do {2330	 ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;2331	 if(ThresholdLow < 0x13) break;2332	 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);2333	 ThresholdLow = 0x13;2334	 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;2335	 if(!temp) break;2336	 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));2337      } while(0);2338 2339   } else ThresholdLow = 2;2340 2341   /* Write CRT/CPU threshold low, CRT/Engine threshold high */2342   temp = (ThresholdLow << 4) | 0x0f;2343   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);2344 2345   temp = (ThresholdLow & 0x10) << 1;2346   if(ModeNo > 0x13) temp |= 0x40;2347   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);2348 2349   /* What is this? */2350   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);2351 2352   /* Write CRT/CPU threshold high */2353   temp = ThresholdLow + 3;2354   if(temp > 0x0f) temp = 0x0f;2355   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);2356}2357 2358unsigned short2359SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)2360{2361   static const unsigned char LatencyFactor[] = {2362		97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */2363		 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */2364		97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */2365		 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */2366		80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */2367		 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */2368		86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */2369		 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */2370   };2371   static const unsigned char LatencyFactor730[] = {2372		 69, 63, 61,2373		 86, 79, 77,2374		103, 96, 94,2375		120,113,111,2376		137,130,1282377   };2378 2379   if(SiS_Pr->ChipType == SIS_730) {2380      return (unsigned short)LatencyFactor730[index];2381   } else {2382      return (unsigned short)LatencyFactor[index];2383   }2384}2385 2386static unsigned short2387SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)2388{2389   unsigned short index;2390 2391   if(SiS_Pr->ChipType == SIS_730) {2392      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);2393   } else {2394      index = (key & 0xe0) >> 5;2395      if(key & 0x10)    index +=  6;2396      if(!(key & 0x01)) index += 24;2397      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;2398   }2399   return SiS_GetLatencyFactor630(SiS_Pr, index);2400}2401 2402static void2403SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2404                    unsigned short RefreshRateTableIndex)2405{2406   unsigned short  ThresholdLow = 0;2407   unsigned short  i, data, VCLK, MCLK16, colorth = 0;2408   unsigned int    templ, datal;2409   const unsigned char *queuedata = NULL;2410   static const unsigned char FQBQData[21] = {2411		0x01,0x21,0x41,0x61,0x81,2412		0x31,0x51,0x71,0x91,0xb1,2413		0x00,0x20,0x40,0x60,0x80,2414		0x30,0x50,0x70,0x90,0xb0,2415		0xff2416   };2417   static const unsigned char FQBQData730[16] = {2418		0x34,0x74,0xb4,2419		0x23,0x63,0xa3,2420		0x12,0x52,0x92,2421		0x01,0x41,0x81,2422		0x00,0x40,0x80,2423		0xff2424   };2425   static const unsigned short colortharray[6] = {2426		1, 1, 2, 2, 3, 42427   };2428 2429   i = 0;2430 2431	if (SiS_Pr->ChipType == SIS_730)2432		queuedata = &FQBQData730[0];2433	else2434		queuedata = &FQBQData[0];2435 2436   if(ModeNo > 0x13) {2437 2438      /* Get VCLK  */2439      if(SiS_Pr->UseCustomMode) {2440	 VCLK = SiS_Pr->CSRClock;2441      } else {2442	 data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);2443	 VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;2444      }2445 2446      /* Get MCLK * 16 */2447      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;2448      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;2449 2450      /* Get half colordepth */2451      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];2452 2453      do {2454	 templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;2455 2456	 datal = templ % MCLK16;2457	 templ = (templ / MCLK16) + 1;2458	 if(datal) templ++;2459 2460	 if(templ > 0x13) {2461	    if(queuedata[i + 1] == 0xFF) {2462	       ThresholdLow = 0x13;2463	       break;2464	    }2465	    i++;2466	 } else {2467	    ThresholdLow = templ;2468	    break;2469	 }2470      } while(queuedata[i] != 0xFF);2471 2472   } else {2473 2474      if(SiS_Pr->ChipType != SIS_730) i = 9;2475      ThresholdLow = 0x02;2476 2477   }2478 2479   /* Write CRT/CPU threshold low, CRT/Engine threshold high */2480   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;2481   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);2482 2483   data = (ThresholdLow & 0x10) << 1;2484   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);2485 2486   /* What is this? */2487   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);2488 2489   /* Write CRT/CPU threshold high (gap = 3) */2490   data = ThresholdLow + 3;2491   if(data > 0x0f) data = 0x0f;2492   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);2493 2494  /* Write foreground and background queue */2495   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);2496 2497   if(SiS_Pr->ChipType == SIS_730) {2498 2499      templ &= 0xfffff9ff;2500      templ |= ((queuedata[i] & 0xc0) << 3);2501 2502   } else {2503 2504      templ &= 0xf0ffffff;2505      if( (ModeNo <= 0x13) &&2506          (SiS_Pr->ChipType == SIS_630) &&2507	  (SiS_Pr->ChipRevision >= 0x30) ) {2508	 templ |= 0x0b000000;2509      } else {2510         templ |= ((queuedata[i] & 0xf0) << 20);2511      }2512 2513   }2514 2515   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);2516   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);2517 2518   /* GUI grant timer (PCI config 0xA3) */2519   if(SiS_Pr->ChipType == SIS_730) {2520 2521      templ &= 0x00ffffff;2522      datal = queuedata[i] << 8;2523      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);2524 2525   } else {2526 2527      templ &= 0xf0ffffff;2528      templ |= ((queuedata[i] & 0x0f) << 24);2529 2530   }2531 2532   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);2533}2534#endif /* CONFIG_FB_SIS_300 */2535 2536#ifdef CONFIG_FB_SIS_3152537static void2538SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)2539{2540   unsigned short modeflag;2541 2542   /* disable auto-threshold */2543   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);2544 2545   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);2546 2547   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);2548   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);2549   if(ModeNo > 0x13) {2550      if(SiS_Pr->ChipType >= XGI_20) {2551	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);2552	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);2553      } else if(SiS_Pr->ChipType >= SIS_661) {2554	 if(!(modeflag & HalfDCLK)) {2555	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);2556	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);2557	 }2558      } else {2559	 if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {2560	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);2561	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);2562	 }2563      }2564   }2565}2566#endif2567 2568/*********************************************/2569/*              MODE REGISTERS               */2570/*********************************************/2571 2572static void2573SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2574		unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)2575{2576   unsigned short data = 0, VCLK = 0, index = 0;2577 2578   if(ModeNo > 0x13) {2579      if(SiS_Pr->UseCustomMode) {2580         VCLK = SiS_Pr->CSRClock;2581      } else {2582         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);2583         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;2584      }2585   }2586 2587   if(SiS_Pr->ChipType < SIS_315H) {2588#ifdef CONFIG_FB_SIS_3002589      if(VCLK > 150) data |= 0x80;2590      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);2591 2592      data = 0x00;2593      if(VCLK >= 150) data |= 0x08;2594      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);2595#endif2596   } else if(SiS_Pr->ChipType < XGI_20) {2597#ifdef CONFIG_FB_SIS_3152598      if(VCLK >= 166) data |= 0x0c;2599      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);2600 2601      if(VCLK >= 166) {2602         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);2603      }2604#endif2605   } else {2606#ifdef CONFIG_FB_SIS_3152607      if(VCLK >= 200) data |= 0x0c;2608      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;2609      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);2610      if(SiS_Pr->ChipType != XGI_20) {2611         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;2612	 if(VCLK < 200) data |= 0x10;2613	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);2614      }2615#endif2616   }2617 2618   /* DAC speed */2619   if(SiS_Pr->ChipType >= SIS_661) {2620 2621      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);2622 2623   } else {2624 2625      data = 0x03;2626      if(VCLK >= 260)      data = 0x00;2627      else if(VCLK >= 160) data = 0x01;2628      else if(VCLK >= 135) data = 0x02;2629 2630      if(SiS_Pr->ChipType == SIS_540) {2631         /* Was == 203 or < 234 which made no sense */2632         if (VCLK < 234) data = 0x02;2633      }2634 2635      if(SiS_Pr->ChipType < SIS_315H) {2636         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);2637      } else {2638         if(SiS_Pr->ChipType > SIS_315PRO) {2639            if(ModeNo > 0x13) data &= 0xfc;2640         }2641         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);2642      }2643 2644   }2645}2646 2647static void2648SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,2649		unsigned short ModeIdIndex, unsigned short RRTI)2650{2651   unsigned short data, infoflag = 0, modeflag;2652#ifdef CONFIG_FB_SIS_3152653   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;2654   unsigned short data2, data3;2655#endif2656 2657   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);2658 2659   if(SiS_Pr->UseCustomMode) {2660      infoflag = SiS_Pr->CInfoFlag;2661   } else {2662      if(ModeNo > 0x13) {2663	 infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;2664      }2665   }2666 2667   /* Disable DPMS */2668   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);2669 2670   data = 0;2671   if(ModeNo > 0x13) {2672      if(SiS_Pr->SiS_ModeType > ModeEGA) {2673         data |= 0x02;2674         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);2675      }2676      if(infoflag & InterlaceMode) data |= 0x20;2677   }2678   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);2679 2680   if(SiS_Pr->ChipType != SIS_300) {2681      data = 0;2682      if(infoflag & InterlaceMode) {2683	 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */2684	 int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |2685		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;2686	 int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |2687		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;2688	 data = hrs - (hto >> 1) + 3;2689      }2690      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);2691      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));2692   }2693 2694   if(modeflag & HalfDCLK) {2695      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);2696   }2697 2698   data = 0;2699   if(modeflag & LineCompareOff) data = 0x08;2700   if(SiS_Pr->ChipType == SIS_300) {2701      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);2702   } else {2703      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;2704      if(SiS_Pr->SiS_ModeType == ModeEGA) {2705	 if(ModeNo > 0x13) {2706	    data |= 0x40;2707	 }2708      }2709      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);2710   }2711 2712#ifdef CONFIG_FB_SIS_3152713   if(SiS_Pr->ChipType >= SIS_315H) {2714      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);2715   }2716 2717   if(SiS_Pr->ChipType == SIS_315PRO) {2718 2719      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];2720      if(SiS_Pr->SiS_ModeType == ModeText) {2721	 data &= 0xc7;2722      } else {2723	 data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;2724	 if(infoflag & InterlaceMode) data2 >>= 1;2725	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;2726	 if(data3) data2 /= data3;2727	 if(data2 >= 0x50) {2728	    data &= 0x0f;2729	    data |= 0x50;2730	 }2731      }2732      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);2733 2734   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {2735 2736      data = SiS_Get310DRAMType(SiS_Pr);2737      if(SiS_Pr->ChipType == SIS_330) {2738	 data = SiS_Pr->SiS_SR15[(2 * 4) + data];2739      } else {2740	 if(SiS_Pr->SiS_ROMNew)	     data = ROMAddr[0xf6];2741	 else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];2742	 else			     data = 0xba;2743      }2744      if(SiS_Pr->SiS_ModeType <= ModeEGA) {2745	 data &= 0xc7;2746      } else {2747	 if(SiS_Pr->UseCustomMode) {2748	    data2 = SiS_Pr->CSRClock;2749	 } else {2750	    data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);2751	    data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;2752	 }2753 2754	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;2755	 if(data3) data2 *= data3;2756 2757	 data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;2758 2759	 if(SiS_Pr->ChipType == SIS_330) {2760	    if(SiS_Pr->SiS_ModeType != Mode16Bpp) {2761	       if     (data2 >= 0x19c) data = 0xba;2762	       else if(data2 >= 0x140) data = 0x7a;2763	       else if(data2 >= 0x101) data = 0x3a;2764	       else if(data2 >= 0xf5)  data = 0x32;2765	       else if(data2 >= 0xe2)  data = 0x2a;2766	       else if(data2 >= 0xc4)  data = 0x22;2767	       else if(data2 >= 0xac)  data = 0x1a;2768	       else if(data2 >= 0x9e)  data = 0x12;2769	       else if(data2 >= 0x8e)  data = 0x0a;2770	       else                    data = 0x02;2771	    } else {2772	       if(data2 >= 0x127)      data = 0xba;2773	       else                    data = 0x7a;2774	    }2775	 } else {  /* 76x+LFB */2776	    if     (data2 >= 0x190) data = 0xba;2777	    else if(data2 >= 0xff)  data = 0x7a;2778	    else if(data2 >= 0xd3)  data = 0x3a;2779	    else if(data2 >= 0xa9)  data = 0x1a;2780	    else if(data2 >= 0x93)  data = 0x0a;2781	    else                    data = 0x02;2782	 }2783      }2784      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);2785 2786   }2787      /* XGI: Nothing. */2788      /* TODO: Check SiS340 */2789#endif2790 2791   data = 0x60;2792   if(SiS_Pr->SiS_ModeType != ModeText) {2793      data ^= 0x60;2794      if(SiS_Pr->SiS_ModeType != ModeEGA) {2795         data ^= 0xA0;2796      }2797   }2798   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);2799 2800   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);2801 2802#ifdef CONFIG_FB_SIS_3152803   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||2804       (SiS_Pr->ChipType == XGI_40)) {2805      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {2806         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);2807      } else {2808         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);2809      }2810   } else if(SiS_Pr->ChipType == XGI_20) {2811      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {2812         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);2813      } else {2814         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);2815      }2816      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);2817   }2818#endif2819}2820 2821#ifdef CONFIG_FB_SIS_3152822static void2823SiS_SetupDualChip(struct SiS_Private *SiS_Pr)2824{2825#if 02826   /* TODO: Find out about IOAddress2 */2827   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;2828   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;2829   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;2830   int i;2831 2832   if((SiS_Pr->ChipRevision != 0) ||2833      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))2834      return;2835 2836   for(i = 0; i <= 4; i++) {					/* SR00 - SR04 */2837      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));2838   }2839   for(i = 0; i <= 8; i++) {					/* GR00 - GR08 */2840      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));2841   }2842   SiS_SetReg(P2_3c4,0x05,0x86);2843   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));	/* SR06 */2844   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));	/* SR21 */2845   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));	/* MISC */2846   SiS_SetReg(P2_3c4,0x05,0x00);2847#endif2848}2849#endif2850 2851/*********************************************/2852/*                 LOAD DAC                  */2853/*********************************************/2854 2855static void2856SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,2857             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)2858{2859   unsigned short d1, d2, d3;2860 2861   switch(dl) {2862   case  0: d1 = dh; d2 = ah; d3 = al; break;2863   case  1: d1 = ah; d2 = al; d3 = dh; break;2864   default: d1 = al; d2 = dh; d3 = ah;2865   }2866   SiS_SetRegByte(DACData, (d1 << shiftflag));2867   SiS_SetRegByte(DACData, (d2 << shiftflag));2868   SiS_SetRegByte(DACData, (d3 << shiftflag));2869}2870 2871void2872SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)2873{2874   unsigned short data, data2, time, i, j, k, m, n, o;2875   unsigned short si, di, bx, sf;2876   SISIOADDRESS DACAddr, DACData;2877   const unsigned char *table = NULL;2878 2879   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;2880 2881   j = time = 64;2882   if(data == 0x00)      table = SiS_MDA_DAC;2883   else if(data == 0x08) table = SiS_CGA_DAC;2884   else if(data == 0x10) table = SiS_EGA_DAC;2885   else if(data == 0x18) {2886      j = 16;2887      time = 256;2888      table = SiS_VGA_DAC;2889   }2890 2891   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */2892         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||2893       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */2894       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */2895      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);2896      DACAddr = SiS_Pr->SiS_P3c8;2897      DACData = SiS_Pr->SiS_P3c9;2898      sf = 0;2899   } else {2900      DACAddr = SiS_Pr->SiS_Part5Port;2901      DACData = SiS_Pr->SiS_Part5Port + 1;2902      sf = 2;2903   }2904 2905   SiS_SetRegByte(DACAddr,0x00);2906 2907   for(i = 0; i < j; i++) {2908      data = table[i];2909      for(k = 0; k < 3; k++) {2910	data2 = 0;2911	if(data & 0x01) data2 += 0x2A;2912	if(data & 0x02) data2 += 0x15;2913	SiS_SetRegByte(DACData, (data2 << sf));2914	data >>= 2;2915      }2916   }2917 2918   if(time == 256) {2919      for(i = 16; i < 32; i++) {2920	 data = table[i] << sf;2921	 for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);2922      }2923      si = 32;2924      for(m = 0; m < 9; m++) {2925	 di = si;2926	 bx = si + 4;2927	 for(n = 0; n < 3; n++) {2928	    for(o = 0; o < 5; o++) {2929	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);2930	       si++;2931	    }2932	    si -= 2;2933	    for(o = 0; o < 3; o++) {2934	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);2935	       si--;2936	    }2937	 }            /* for n < 3 */2938	 si += 5;2939      }               /* for m < 9 */2940   }2941}2942 2943/*********************************************/2944/*         SET CRT1 REGISTER GROUP           */2945/*********************************************/2946 2947static void2948SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)2949{2950   unsigned short StandTableIndex, RefreshRateTableIndex;2951 2952   SiS_Pr->SiS_CRT1Mode = ModeNo;2953 2954   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);2955 2956   if(SiS_Pr->SiS_SetFlag & LowModeTests) {2957      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {2958         SiS_DisableBridge(SiS_Pr);2959      }2960   }2961 2962   SiS_ResetSegmentRegisters(SiS_Pr);2963 2964   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);2965   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);2966   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);2967   SiS_SetATTRegs(SiS_Pr, StandTableIndex);2968   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);2969   SiS_ClearExt1Regs(SiS_Pr, ModeNo);2970   SiS_ResetCRT1VCLK(SiS_Pr);2971 2972   SiS_Pr->SiS_SelectCRT2Rate = 0;2973   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);2974 2975   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {2976      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {2977         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;2978      }2979   }2980 2981   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {2982      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;2983   }2984 2985   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);2986 2987   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {2988      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;2989   }2990 2991   if(RefreshRateTableIndex != 0xFFFF) {2992      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);2993      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);2994      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);2995      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);2996   }2997 2998   switch(SiS_Pr->ChipType) {2999#ifdef CONFIG_FB_SIS_3003000   case SIS_300:3001      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);3002      break;3003   case SIS_540:3004   case SIS_630:3005   case SIS_730:3006      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);3007      break;3008#endif3009   default:3010#ifdef CONFIG_FB_SIS_3153011      if(SiS_Pr->ChipType == XGI_20) {3012         unsigned char sr2b = 0, sr2c = 0;3013         switch(ModeNo) {3014	 case 0x00:3015	 case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;3016	 case 0x04:3017	 case 0x05:3018	 case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;3019	 }3020	 if(sr2b) {3021            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);3022	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);3023	    SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));3024	 }3025      }3026      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);3027#endif3028      break;3029   }3030 3031   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);3032 3033#ifdef CONFIG_FB_SIS_3153034   if(SiS_Pr->ChipType == XGI_40) {3035      SiS_SetupDualChip(SiS_Pr);3036   }3037#endif3038 3039   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);3040 3041   if(SiS_Pr->SiS_flag_clearbuffer) {3042      SiS_ClearBuffer(SiS_Pr, ModeNo);3043   }3044 3045   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {3046      SiS_WaitRetrace1(SiS_Pr);3047      SiS_DisplayOn(SiS_Pr);3048   }3049}3050 3051/*********************************************/3052/*       HELPER: VIDEO BRIDGE PROG CLK       */3053/*********************************************/3054 3055static void3056SiS_InitVB(struct SiS_Private *SiS_Pr)3057{3058   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;3059 3060   SiS_Pr->Init_P4_0E = 0;3061   if(SiS_Pr->SiS_ROMNew) {3062      SiS_Pr->Init_P4_0E = ROMAddr[0x82];3063   } else if(SiS_Pr->ChipType >= XGI_40) {3064      if(SiS_Pr->SiS_XGIROM) {3065         SiS_Pr->Init_P4_0E = ROMAddr[0x80];3066      }3067   }3068}3069 3070static void3071SiS_ResetVB(struct SiS_Private *SiS_Pr)3072{3073#ifdef CONFIG_FB_SIS_3153074   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;3075   unsigned short temp;3076 3077   /* VB programming clock */3078   if(SiS_Pr->SiS_UseROM) {3079      if(SiS_Pr->ChipType < SIS_330) {3080	 temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;3081	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;3082	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);3083      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {3084	 temp = ROMAddr[0x7e] | 0x40;3085	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;3086	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);3087      }3088   } else if(SiS_Pr->ChipType >= XGI_40) {3089      temp = 0x40;3090      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];3091      /* Can we do this on any chipset? */3092      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);3093   }3094#endif3095}3096 3097/*********************************************/3098/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */3099/*********************************************/3100 3101static void3102SiS_StrangeStuff(struct SiS_Private *SiS_Pr)3103{3104   /* SiS65x and XGI set up some sort of "lock mode" for text3105    * which locks CRT2 in some way to CRT1 timing. Disable3106    * this here.3107    */3108#ifdef CONFIG_FB_SIS_3153109   if((IS_SIS651) || (IS_SISM650) ||3110      SiS_Pr->ChipType == SIS_340 ||3111      SiS_Pr->ChipType == XGI_40) {3112      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */3113      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);3114      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */3115      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */3116      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);3117   }3118   /* !!! This does not support modes < 0x13 !!! */3119#endif3120}3121 3122/*********************************************/3123/*     HELPER: SET AGP TIMING FOR SiS760     */3124/*********************************************/3125 3126static void3127SiS_Handle760(struct SiS_Private *SiS_Pr)3128{3129#ifdef CONFIG_FB_SIS_3153130   unsigned int somebase;3131   unsigned char temp1, temp2, temp3;3132 3133   if( (SiS_Pr->ChipType != SIS_760)                         ||3134       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||3135       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||3136       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )3137      return;3138 3139   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);3140   somebase &= 0xffff;3141 3142   if(somebase == 0) return;3143 3144   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;3145 3146   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {3147      temp1 = 0x21;3148      temp2 = 0x03;3149      temp3 |= 0x08;3150   } else {3151      temp1 = 0x25;3152      temp2 = 0x0b;3153   }3154 3155   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);3156   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);3157 3158   SiS_SetRegByte((somebase + 0x85), temp3);3159#endif3160}3161 3162/*********************************************/3163/*                 SiSSetMode()              */3164/*********************************************/3165 3166bool3167SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)3168{3169   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;3170   unsigned short RealModeNo, ModeIdIndex;3171   unsigned char  backupreg = 0;3172   unsigned short KeepLockReg;3173 3174   SiS_Pr->UseCustomMode = false;3175   SiS_Pr->CRT1UsesCustomMode = false;3176 3177   SiS_Pr->SiS_flag_clearbuffer = 0;3178 3179   if(SiS_Pr->UseCustomMode) {3180      ModeNo = 0xfe;3181   } else {3182      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;3183      ModeNo &= 0x7f;3184   }3185 3186   /* Don't use FSTN mode for CRT1 */3187   RealModeNo = ModeNo;3188   if(ModeNo == 0x5b) ModeNo = 0x56;3189 3190   SiSInitPtr(SiS_Pr);3191   SiSRegInit(SiS_Pr, BaseAddr);3192   SiS_GetSysFlags(SiS_Pr);3193 3194   SiS_Pr->SiS_VGAINFO = 0x11;3195 3196   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);3197   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);3198 3199   SiSInitPCIetc(SiS_Pr);3200   SiSSetLVDSetc(SiS_Pr);3201   SiSDetermineROMUsage(SiS_Pr);3202 3203   SiS_UnLockCRT2(SiS_Pr);3204 3205   if(!SiS_Pr->UseCustomMode) {3206      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;3207   } else {3208      ModeIdIndex = 0;3209   }3210 3211   SiS_GetVBType(SiS_Pr);3212 3213   /* Init/restore some VB registers */3214   SiS_InitVB(SiS_Pr);3215   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {3216      if(SiS_Pr->ChipType >= SIS_315H) {3217         SiS_ResetVB(SiS_Pr);3218	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);3219	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);3220         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);3221      } else {3222         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);3223      }3224   }3225 3226   /* Get VB information (connectors, connected devices) */3227   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);3228   SiS_SetYPbPr(SiS_Pr);3229   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);3230   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);3231   SiS_SetLowModeTest(SiS_Pr, ModeNo);3232 3233   /* Check memory size (kernel framebuffer driver only) */3234   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {3235      return false;3236   }3237 3238   SiS_OpenCRTC(SiS_Pr);3239 3240   if(SiS_Pr->UseCustomMode) {3241      SiS_Pr->CRT1UsesCustomMode = true;3242      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;3243      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;3244   } else {3245      SiS_Pr->CRT1UsesCustomMode = false;3246   }3247 3248   /* Set mode on CRT1 */3249   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||3250       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {3251      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);3252   }3253 3254   /* Set mode on CRT2 */3255   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {3256      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||3257	  (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||3258	  (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||3259	  (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {3260	 SiS_SetCRT2Group(SiS_Pr, RealModeNo);3261      }3262   }3263 3264   SiS_HandleCRT1(SiS_Pr);3265 3266   SiS_StrangeStuff(SiS_Pr);3267 3268   SiS_DisplayOn(SiS_Pr);3269   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);3270 3271#ifdef CONFIG_FB_SIS_3153272   if(SiS_Pr->ChipType >= SIS_315H) {3273      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {3274	 if(!(SiS_IsDualEdge(SiS_Pr))) {3275	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);3276	 }3277      }3278   }3279#endif3280 3281   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {3282      if(SiS_Pr->ChipType >= SIS_315H) {3283#ifdef CONFIG_FB_SIS_3153284	 if(!SiS_Pr->SiS_ROMNew) {3285	    if(SiS_IsVAMode(SiS_Pr)) {3286	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);3287	    } else {3288	       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);3289	    }3290	 }3291 3292	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);3293 3294	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {3295	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {3296	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);3297	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);3298	    }3299	 }3300 3301	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {3302	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);3303	 }3304#endif3305      } else if((SiS_Pr->ChipType == SIS_630) ||3306	        (SiS_Pr->ChipType == SIS_730)) {3307	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);3308      }3309   }3310 3311   SiS_CloseCRTC(SiS_Pr);3312 3313   SiS_Handle760(SiS_Pr);3314 3315   /* We never lock registers in XF86 */3316   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);3317 3318   return true;3319}3320 3321#ifndef GETBITSTR3322#define GENBITSMASK(mask)   	GENMASK(1?mask,0?mask)3323#define GETBITS(var,mask)   	(((var) & GENBITSMASK(mask)) >> (0?mask))3324#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))3325#endif3326 3327void3328SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)3329{3330   int x = 1; /* Fix sync */3331 3332   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */3333   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */3334   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */3335   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */3336   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */3337   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */3338			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);3339 3340   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;			/* CR6 */3341   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)		/* CR7 */3342			  | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)3343			  | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)3344			  | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)3345			  | 0x103346			  | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)3347			  | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)3348			  | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);3349 3350   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */3351 3352   if(depth != 8) {3353      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */3354      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;3355   }3356 3357   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;			/* CR10 */3358   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;		/* CR11 */3359   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */3360   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */3361   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */3362 3363   SiS_Pr->CCRT1CRTC[13] =							/* SRA */3364			GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |3365			GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |3366			GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |3367			GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |3368			GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |3369			GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;3370 3371   SiS_Pr->CCRT1CRTC[14] =							/* SRB */3372			GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |3373			GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |3374			GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |3375			GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;3376 3377 3378   SiS_Pr->CCRT1CRTC[15] =							/* SRC */3379			GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |3380			GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;3381}3382 3383void3384SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,3385		unsigned short ModeIdIndex)3386{3387   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;3388   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;3389   int i, j;3390 3391   /* 1:1 data: use data set by setcrt1crtc() */3392   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;3393 3394   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);3395 3396   if(modeflag & HalfDCLK) VGAHDE >>= 1;3397 3398   SiS_Pr->CHDisplay = VGAHDE;3399   SiS_Pr->CHBlankStart = VGAHDE;3400 3401   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;3402   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;3403 3404   if(SiS_Pr->ChipType < SIS_315H) {3405#ifdef CONFIG_FB_SIS_3003406      tempbx = SiS_Pr->SiS_VGAHT;3407      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3408         tempbx = SiS_Pr->PanelHT;3409      }3410      if(modeflag & HalfDCLK) tempbx >>= 1;3411      remaining = tempbx % 8;3412#endif3413   } else {3414#ifdef CONFIG_FB_SIS_3153415      /* OK for LCDA, LVDS */3416      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;3417      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */3418      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3419         tempax = SiS_Pr->PanelXRes;3420      }3421      tempbx += tempax;3422      if(modeflag & HalfDCLK) tempbx -= VGAHDE;3423#endif3424   }3425   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;3426 3427   if(SiS_Pr->ChipType < SIS_315H) {3428#ifdef CONFIG_FB_SIS_3003429      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {3430	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);3431	 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;3432	 if(modeflag & HalfDCLK) {3433	    SiS_Pr->CHSyncStart >>= 1;3434	    SiS_Pr->CHSyncEnd >>= 1;3435	 }3436      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3437	 tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;3438	 tempbx = (SiS_Pr->PanelHRS + 1) & ~1;3439	 if(modeflag & HalfDCLK) {3440	    tempax >>= 1;3441	    tempbx >>= 1;3442	 }3443	 SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;3444	 tempax = SiS_Pr->PanelHRE + 7;3445	 if(modeflag & HalfDCLK) tempax >>= 1;3446	 SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;3447      } else {3448	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;3449	 if(modeflag & HalfDCLK) {3450	    SiS_Pr->CHSyncStart >>= 1;3451	    tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;3452	    SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;3453	 } else {3454	    SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;3455	    SiS_Pr->CHSyncStart += 8;3456	 }3457      }3458#endif3459   } else {3460#ifdef CONFIG_FB_SIS_3153461      tempax = VGAHDE;3462      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3463	 tempbx = SiS_Pr->PanelXRes;3464	 if(modeflag & HalfDCLK) tempbx >>= 1;3465	 tempax += ((tempbx - tempax) >> 1);3466      }3467      tempax += SiS_Pr->PanelHRS;3468      SiS_Pr->CHSyncStart = tempax;3469      tempax += SiS_Pr->PanelHRE;3470      SiS_Pr->CHSyncEnd = tempax;3471#endif3472   }3473 3474   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;3475   tempax = SiS_Pr->SiS_VGAVDE;3476   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3477      tempax = SiS_Pr->PanelYRes;3478   } else if(SiS_Pr->ChipType < SIS_315H) {3479#ifdef CONFIG_FB_SIS_3003480      /* Stupid hack for 640x400/320x200 */3481      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {3482	 if((tempax + tempbx) == 438) tempbx += 16;3483      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||3484		(SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {3485	 tempax = 0;3486	 tempbx = SiS_Pr->SiS_VGAVT;3487      }3488#endif3489   }3490   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;3491 3492   tempax = SiS_Pr->SiS_VGAVDE;3493   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {3494      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;3495   }3496   tempax += SiS_Pr->PanelVRS;3497   SiS_Pr->CVSyncStart = tempax;3498   tempax += SiS_Pr->PanelVRE;3499   SiS_Pr->CVSyncEnd = tempax;3500   if(SiS_Pr->ChipType < SIS_315H) {3501      SiS_Pr->CVSyncStart--;3502      SiS_Pr->CVSyncEnd--;3503   }3504 3505   SiS_CalcCRRegisters(SiS_Pr, 8);3506   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;3507   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);3508   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;3509 3510   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);3511 3512   for(i = 0, j = 0; i <= 7; i++, j++) {3513      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);3514   }3515   for(j = 0x10; i <= 10; i++, j++) {3516      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);3517   }3518   for(j = 0x15; i <= 12; i++, j++) {3519      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);3520   }3521   for(j = 0x0A; i <= 15; i++, j++) {3522      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);3523   }3524 3525   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;3526   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);3527 3528   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;3529   if(modeflag & DoubleScanMode) tempax |= 0x80;3530   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);3531 3532}3533 3534void3535SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,3536			int xres, int yres,3537			struct fb_var_screeninfo *var, bool writeres3538)3539{3540   unsigned short HRE, HBE, HRS, HDE;3541   unsigned short VRE, VBE, VRS, VDE;3542   unsigned char  sr_data, cr_data;3543   int            B, C, D, E, F, temp;3544 3545   sr_data = crdata[14];3546 3547   /* Horizontal display enable end */3548   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);3549   E = HDE + 1;3550 3551   /* Horizontal retrace (=sync) start */3552   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);3553   F = HRS - E - 3;3554 3555   sr_data = crdata[15];3556   cr_data = crdata[5];3557 3558   /* Horizontal blank end */3559   HBE = (crdata[3] & 0x1f) |3560         ((unsigned short)(cr_data & 0x80) >> 2) |3561         ((unsigned short)(sr_data & 0x03) << 6);3562 3563   /* Horizontal retrace (=sync) end */3564   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);3565 3566   temp = HBE - ((E - 1) & 255);3567   B = (temp > 0) ? temp : (temp + 256);3568 3569   temp = HRE - ((E + F + 3) & 63);3570   C = (temp > 0) ? temp : (temp + 64);3571 3572   D = B - F - C;3573 3574   if(writeres) var->xres = xres = E * 8;3575   var->left_margin = D * 8;3576   var->right_margin = F * 8;3577   var->hsync_len = C * 8;3578 3579   /* Vertical */3580   sr_data = crdata[13];3581   cr_data = crdata[7];3582 3583   /* Vertical display enable end */3584   VDE = crdata[10] |3585	 ((unsigned short)(cr_data & 0x02) << 7) |3586	 ((unsigned short)(cr_data & 0x40) << 3) |3587	 ((unsigned short)(sr_data & 0x02) << 9);3588   E = VDE + 1;3589 3590   /* Vertical retrace (=sync) start */3591   VRS = crdata[8] |3592	 ((unsigned short)(cr_data & 0x04) << 6) |3593	 ((unsigned short)(cr_data & 0x80) << 2) |3594	 ((unsigned short)(sr_data & 0x08) << 7);3595   F = VRS + 1 - E;3596 3597   /* Vertical blank end */3598   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);3599   temp = VBE - ((E - 1) & 511);3600   B = (temp > 0) ? temp : (temp + 512);3601 3602   /* Vertical retrace (=sync) end */3603   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);3604   temp = VRE - ((E + F - 1) & 31);3605   C = (temp > 0) ? temp : (temp + 32);3606 3607   D = B - F - C;3608 3609   if(writeres) var->yres = yres = E;3610   var->upper_margin = D;3611   var->lower_margin = F;3612   var->vsync_len = C;3613 3614   if((xres == 320) && ((yres == 200) || (yres == 240))) {3615	/* Terrible hack, but correct CRTC data for3616	 * these modes only produces a black screen...3617	 * (HRE is 0, leading into a too large C and3618	 * a negative D. The CRT controller does not3619	 * seem to like correcting HRE to 50)3620	 */3621      var->left_margin = (400 - 376);3622      var->right_margin = (328 - 320);3623      var->hsync_len = (376 - 328);3624 3625   }3626 3627}3628 3629 3630 3631 3632