linux/drivers/video/fbdev/sis/init.c
<<
>>
Prefs
   1/* $XFree86$ */
   2/* $XdotOrg$ */
   3/*
   4 * Mode initializing code (CRT1 section) for
   5 * 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, Z7
   8 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
   9 *
  10 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  11 *
  12 * If distributed as part of the Linux kernel, the following license terms
  13 * apply:
  14 *
  15 * * This program is free software; you can redistribute it and/or modify
  16 * * it under the terms of the GNU General Public License as published by
  17 * * 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 of
  22 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23 * * GNU General Public License for more details.
  24 * *
  25 * * You should have received a copy of the GNU General Public License
  26 * * along with this program; if not, write to the Free Software
  27 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  28 *
  29 * Otherwise, the following license terms apply:
  30 *
  31 * * Redistribution and use in source and binary forms, with or without
  32 * * modification, are permitted provided that the following conditions
  33 * * are met:
  34 * * 1) Redistributions of source code must retain the above copyright
  35 * *    notice, this list of conditions and the following disclaimer.
  36 * * 2) Redistributions in binary form must reproduce the above copyright
  37 * *    notice, this list of conditions and the following disclaimer in the
  38 * *    documentation and/or other materials provided with the distribution.
  39 * * 3) The name of the author may not be used to endorse or promote products
  40 * *    derived from this software without specific prior written permission.
  41 * *
  42 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  43 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  44 * * 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, BUT
  47 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  48 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  49 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  50 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  51 * * 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_300
  62#include "300vtbl.h"
  63#endif
  64
  65#ifdef CONFIG_FB_SIS_315
  66#include "310vtbl.h"
  67#endif
  68
  69#if defined(ALLOC_PRAGMA)
  70#pragma alloc_text(PAGE,SiSSetMode)
  71#endif
  72
  73/*********************************************/
  74/*         POINTER INITIALIZATION            */
  75/*********************************************/
  76
  77#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  78static void
  79InitCommonPointer(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 0
  95   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
  96   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
  97#endif
  98
  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 0
 145   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#endif
 150
 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#endif
 158
 159#ifdef CONFIG_FB_SIS_300
 160static void
 161InitTo300Pointer(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#endif
 235
 236#ifdef CONFIG_FB_SIS_315
 237static void
 238InitTo310Pointer(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#endif
 315
 316bool
 317SiSInitPtr(struct SiS_Private *SiS_Pr)
 318{
 319   if(SiS_Pr->ChipType < SIS_315H) {
 320#ifdef CONFIG_FB_SIS_300
 321      InitTo300Pointer(SiS_Pr);
 322#else
 323      return false;
 324#endif
 325   } else {
 326#ifdef CONFIG_FB_SIS_315
 327      InitTo310Pointer(SiS_Pr);
 328#else
 329      return false;
 330#endif
 331   }
 332   return true;
 333}
 334
 335/*********************************************/
 336/*            HELPER: Get ModeID             */
 337/*********************************************/
 338
 339static
 340unsigned short
 341SiS_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                        else
 354                                ModeIndex = ModeIndex_320x240[Depth];
 355                }
 356                break;
 357        case 400:
 358                if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
 359                        if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 360                }
 361                break;
 362        case 512:
 363                if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 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 short
 479SiS_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_1600
 700        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#endif
 722      }
 723   }
 724
 725   return ModeIndex;
 726}
 727
 728unsigned short
 729SiS_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 short
 848SiS_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
 879void
 880SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
 881{
 882        outb(index, port);
 883        outb(data, port + 1);
 884}
 885
 886void
 887SiS_SetRegByte(SISIOADDRESS port, u8 data)
 888{
 889        outb(data, port);
 890}
 891
 892void
 893SiS_SetRegShort(SISIOADDRESS port, u16 data)
 894{
 895        outw(data, port);
 896}
 897
 898void
 899SiS_SetRegLong(SISIOADDRESS port, u32 data)
 900{
 901        outl(data, port);
 902}
 903
 904u8
 905SiS_GetReg(SISIOADDRESS port, u8 index)
 906{
 907        outb(index, port);
 908        return inb(port + 1);
 909}
 910
 911u8
 912SiS_GetRegByte(SISIOADDRESS port)
 913{
 914        return inb(port);
 915}
 916
 917u16
 918SiS_GetRegShort(SISIOADDRESS port)
 919{
 920        return inw(port);
 921}
 922
 923u32
 924SiS_GetRegLong(SISIOADDRESS port)
 925{
 926        return inl(port);
 927}
 928
 929void
 930SiS_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
 939void
 940SiS_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
 949void
 950SiS_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
 963void
 964SiS_DisplayOn(struct SiS_Private *SiS_Pr)
 965{
 966   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 967}
 968
 969void
 970SiS_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
 980void
 981SiSRegInit(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 void
1012SiS_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 void
1084SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1085{
1086   switch(SiS_Pr->ChipType) {
1087#ifdef CONFIG_FB_SIS_300
1088   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#endif
1106#ifdef CONFIG_FB_SIS_315
1107   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 3D
1137       */
1138      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
1139      break;
1140#endif
1141   default:
1142      break;
1143   }
1144}
1145
1146/*********************************************/
1147/*             HELPER: SetLVDSetc            */
1148/*********************************************/
1149
1150static
1151void
1152SiSSetLVDSetc(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_300
1171   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#endif
1184#ifdef CONFIG_FB_SIS_315
1185   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#endif
1207   default:
1208        break;
1209   }
1210}
1211
1212/*********************************************/
1213/*          HELPER: Enable DSTN/FSTN         */
1214/*********************************************/
1215
1216void
1217SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
1218{
1219   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
1220}
1221
1222void
1223SiS_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 short
1233SiS_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
1249bool
1250SiSDetermineROMLayout661(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 void
1290SiSDetermineROMUsage(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 by
1304          * checking the jmp instruction at the beginning
1305          * 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 perhaps
1311          * the others do as well
1312          */
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 void
1346SiS_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 void
1360SiS_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 void
1374SiS_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 void
1381SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
1382{
1383   SiS_SetSegmentReg(SiS_Pr, 0);
1384}
1385
1386static void
1387SiS_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 void
1398SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
1399{
1400   SiS_SetSegmentRegOver(SiS_Pr, 0);
1401}
1402
1403static void
1404SiS_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
1416static
1417void
1418SiS_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 bool
1482SiS_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_315
1500static unsigned char
1501SiS_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 short
1543SiS_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#endif
1561
1562/*********************************************/
1563/*           HELPER: ClearBuffer             */
1564/*********************************************/
1565
1566static void
1567SiS_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
1595bool
1596SiS_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 short
1637SiS_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 short
1655SiS_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 short
1669SiS_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 bool
1687SiS_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 void
1714SiS_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 void
1726SiS_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 void
1743SiS_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#endif
1756}
1757
1758static void
1759SiS_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 0
1764   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#endif
1771}
1772
1773/*********************************************/
1774/*           HELPER: GetColorDepth           */
1775/*********************************************/
1776
1777unsigned short
1778SiS_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 short
1804SiS_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 void
1832SiS_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 void
1864SiS_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 void
1886SiS_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 void
1921SiS_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 void
1981SiS_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 void
2002SiS_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 void
2025SiS_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 void
2053SiS_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 void
2073SiS_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_315
2123   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#endif
2134}
2135
2136/*********************************************/
2137/*               OFFSET & PITCH              */
2138/*********************************************/
2139/*  (partly overruled by SetPitch() in XF86) */
2140/*********************************************/
2141
2142static void
2143SiS_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 void
2177SiS_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_315
2206      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#endif
2217   } else {
2218      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2219   }
2220}
2221
2222/*********************************************/
2223/*                  FIFO                     */
2224/*********************************************/
2225
2226#ifdef CONFIG_FB_SIS_300
2227void
2228SiS_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, 2
2234   };
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 short
2244SiS_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,11
2250   };
2251
2252   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
2253}
2254
2255unsigned short
2256SiS_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,12
2262   };
2263
2264   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
2265}
2266
2267static unsigned short
2268SiS_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 short
2288SiS_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 void
2302SiS_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 short
2359SiS_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,128
2377   };
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 short
2387SiS_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 void
2403SiS_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                0xff
2416   };
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                0xff
2424   };
2425   static const unsigned short colortharray[6] = {
2426                1, 1, 2, 2, 3, 4
2427   };
2428
2429   i = 0;
2430
2431   if(ModeNo > 0x13) {
2432
2433      /* Get VCLK  */
2434      if(SiS_Pr->UseCustomMode) {
2435         VCLK = SiS_Pr->CSRClock;
2436      } else {
2437         data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2438         VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
2439      }
2440
2441      /* Get MCLK * 16 */
2442      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
2443      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
2444
2445      /* Get half colordepth */
2446      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2447
2448      if(SiS_Pr->ChipType == SIS_730) {
2449         queuedata = &FQBQData730[0];
2450      } else {
2451         queuedata = &FQBQData[0];
2452      }
2453
2454      do {
2455         templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
2456
2457         datal = templ % MCLK16;
2458         templ = (templ / MCLK16) + 1;
2459         if(datal) templ++;
2460
2461         if(templ > 0x13) {
2462            if(queuedata[i + 1] == 0xFF) {
2463               ThresholdLow = 0x13;
2464               break;
2465            }
2466            i++;
2467         } else {
2468            ThresholdLow = templ;
2469            break;
2470         }
2471      } while(queuedata[i] != 0xFF);
2472
2473   } else {
2474
2475      if(SiS_Pr->ChipType != SIS_730) i = 9;
2476      ThresholdLow = 0x02;
2477
2478   }
2479
2480   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2481   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
2482   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
2483
2484   data = (ThresholdLow & 0x10) << 1;
2485   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
2486
2487   /* What is this? */
2488   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2489
2490   /* Write CRT/CPU threshold high (gap = 3) */
2491   data = ThresholdLow + 3;
2492   if(data > 0x0f) data = 0x0f;
2493   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
2494
2495  /* Write foreground and background queue */
2496   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
2497
2498   if(SiS_Pr->ChipType == SIS_730) {
2499
2500      templ &= 0xfffff9ff;
2501      templ |= ((queuedata[i] & 0xc0) << 3);
2502
2503   } else {
2504
2505      templ &= 0xf0ffffff;
2506      if( (ModeNo <= 0x13) &&
2507          (SiS_Pr->ChipType == SIS_630) &&
2508          (SiS_Pr->ChipRevision >= 0x30) ) {
2509         templ |= 0x0b000000;
2510      } else {
2511         templ |= ((queuedata[i] & 0xf0) << 20);
2512      }
2513
2514   }
2515
2516   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
2517   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
2518
2519   /* GUI grant timer (PCI config 0xA3) */
2520   if(SiS_Pr->ChipType == SIS_730) {
2521
2522      templ &= 0x00ffffff;
2523      datal = queuedata[i] << 8;
2524      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
2525
2526   } else {
2527
2528      templ &= 0xf0ffffff;
2529      templ |= ((queuedata[i] & 0x0f) << 24);
2530
2531   }
2532
2533   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
2534}
2535#endif /* CONFIG_FB_SIS_300 */
2536
2537#ifdef CONFIG_FB_SIS_315
2538static void
2539SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2540{
2541   unsigned short modeflag;
2542
2543   /* disable auto-threshold */
2544   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
2545
2546   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2547
2548   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
2549   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
2550   if(ModeNo > 0x13) {
2551      if(SiS_Pr->ChipType >= XGI_20) {
2552         SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2553         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2554      } else if(SiS_Pr->ChipType >= SIS_661) {
2555         if(!(modeflag & HalfDCLK)) {
2556            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2557            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2558         }
2559      } else {
2560         if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
2561            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2562            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2563         }
2564      }
2565   }
2566}
2567#endif
2568
2569/*********************************************/
2570/*              MODE REGISTERS               */
2571/*********************************************/
2572
2573static void
2574SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2575                unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
2576{
2577   unsigned short data = 0, VCLK = 0, index = 0;
2578
2579   if(ModeNo > 0x13) {
2580      if(SiS_Pr->UseCustomMode) {
2581         VCLK = SiS_Pr->CSRClock;
2582      } else {
2583         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2584         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2585      }
2586   }
2587
2588   if(SiS_Pr->ChipType < SIS_315H) {
2589#ifdef CONFIG_FB_SIS_300
2590      if(VCLK > 150) data |= 0x80;
2591      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
2592
2593      data = 0x00;
2594      if(VCLK >= 150) data |= 0x08;
2595      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
2596#endif
2597   } else if(SiS_Pr->ChipType < XGI_20) {
2598#ifdef CONFIG_FB_SIS_315
2599      if(VCLK >= 166) data |= 0x0c;
2600      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2601
2602      if(VCLK >= 166) {
2603         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
2604      }
2605#endif
2606   } else {
2607#ifdef CONFIG_FB_SIS_315
2608      if(VCLK >= 200) data |= 0x0c;
2609      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
2610      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2611      if(SiS_Pr->ChipType != XGI_20) {
2612         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
2613         if(VCLK < 200) data |= 0x10;
2614         SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
2615      }
2616#endif
2617   }
2618
2619   /* DAC speed */
2620   if(SiS_Pr->ChipType >= SIS_661) {
2621
2622      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
2623
2624   } else {
2625
2626      data = 0x03;
2627      if(VCLK >= 260)      data = 0x00;
2628      else if(VCLK >= 160) data = 0x01;
2629      else if(VCLK >= 135) data = 0x02;
2630
2631      if(SiS_Pr->ChipType == SIS_540) {
2632         /* Was == 203 or < 234 which made no sense */
2633         if (VCLK < 234) data = 0x02;
2634      }
2635
2636      if(SiS_Pr->ChipType < SIS_315H) {
2637         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
2638      } else {
2639         if(SiS_Pr->ChipType > SIS_315PRO) {
2640            if(ModeNo > 0x13) data &= 0xfc;
2641         }
2642         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
2643      }
2644
2645   }
2646}
2647
2648static void
2649SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2650                unsigned short ModeIdIndex, unsigned short RRTI)
2651{
2652   unsigned short data, infoflag = 0, modeflag, resindex;
2653#ifdef CONFIG_FB_SIS_315
2654   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
2655   unsigned short data2, data3;
2656#endif
2657
2658   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2659
2660   if(SiS_Pr->UseCustomMode) {
2661      infoflag = SiS_Pr->CInfoFlag;
2662   } else {
2663      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
2664      if(ModeNo > 0x13) {
2665         infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2666      }
2667   }
2668
2669   /* Disable DPMS */
2670   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
2671
2672   data = 0;
2673   if(ModeNo > 0x13) {
2674      if(SiS_Pr->SiS_ModeType > ModeEGA) {
2675         data |= 0x02;
2676         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
2677      }
2678      if(infoflag & InterlaceMode) data |= 0x20;
2679   }
2680   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
2681
2682   if(SiS_Pr->ChipType != SIS_300) {
2683      data = 0;
2684      if(infoflag & InterlaceMode) {
2685         /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
2686         int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
2687                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
2688         int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
2689                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
2690         data = hrs - (hto >> 1) + 3;
2691      }
2692      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
2693      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
2694   }
2695
2696   if(modeflag & HalfDCLK) {
2697      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
2698   }
2699
2700   data = 0;
2701   if(modeflag & LineCompareOff) data = 0x08;
2702   if(SiS_Pr->ChipType == SIS_300) {
2703      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
2704   } else {
2705      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
2706      if(SiS_Pr->SiS_ModeType == ModeEGA) {
2707         if(ModeNo > 0x13) {
2708            data |= 0x40;
2709         }
2710      }
2711      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
2712   }
2713
2714#ifdef CONFIG_FB_SIS_315
2715   if(SiS_Pr->ChipType >= SIS_315H) {
2716      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
2717   }
2718
2719   if(SiS_Pr->ChipType == SIS_315PRO) {
2720
2721      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
2722      if(SiS_Pr->SiS_ModeType == ModeText) {
2723         data &= 0xc7;
2724      } else {
2725         data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
2726         if(infoflag & InterlaceMode) data2 >>= 1;
2727         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2728         if(data3) data2 /= data3;
2729         if(data2 >= 0x50) {
2730            data &= 0x0f;
2731            data |= 0x50;
2732         }
2733      }
2734      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2735
2736   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
2737
2738      data = SiS_Get310DRAMType(SiS_Pr);
2739      if(SiS_Pr->ChipType == SIS_330) {
2740         data = SiS_Pr->SiS_SR15[(2 * 4) + data];
2741      } else {
2742         if(SiS_Pr->SiS_ROMNew)      data = ROMAddr[0xf6];
2743         else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
2744         else                        data = 0xba;
2745      }
2746      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
2747         data &= 0xc7;
2748      } else {
2749         if(SiS_Pr->UseCustomMode) {
2750            data2 = SiS_Pr->CSRClock;
2751         } else {
2752            data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2753            data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
2754         }
2755
2756         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2757         if(data3) data2 *= data3;
2758
2759         data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
2760
2761         if(SiS_Pr->ChipType == SIS_330) {
2762            if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
2763               if     (data2 >= 0x19c) data = 0xba;
2764               else if(data2 >= 0x140) data = 0x7a;
2765               else if(data2 >= 0x101) data = 0x3a;
2766               else if(data2 >= 0xf5)  data = 0x32;
2767               else if(data2 >= 0xe2)  data = 0x2a;
2768               else if(data2 >= 0xc4)  data = 0x22;
2769               else if(data2 >= 0xac)  data = 0x1a;
2770               else if(data2 >= 0x9e)  data = 0x12;
2771               else if(data2 >= 0x8e)  data = 0x0a;
2772               else                    data = 0x02;
2773            } else {
2774               if(data2 >= 0x127)      data = 0xba;
2775               else                    data = 0x7a;
2776            }
2777         } else {  /* 76x+LFB */
2778            if     (data2 >= 0x190) data = 0xba;
2779            else if(data2 >= 0xff)  data = 0x7a;
2780            else if(data2 >= 0xd3)  data = 0x3a;
2781            else if(data2 >= 0xa9)  data = 0x1a;
2782            else if(data2 >= 0x93)  data = 0x0a;
2783            else                    data = 0x02;
2784         }
2785      }
2786      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2787
2788   }
2789      /* XGI: Nothing. */
2790      /* TODO: Check SiS340 */
2791#endif
2792
2793   data = 0x60;
2794   if(SiS_Pr->SiS_ModeType != ModeText) {
2795      data ^= 0x60;
2796      if(SiS_Pr->SiS_ModeType != ModeEGA) {
2797         data ^= 0xA0;
2798      }
2799   }
2800   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
2801
2802   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
2803
2804#ifdef CONFIG_FB_SIS_315
2805   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
2806       (SiS_Pr->ChipType == XGI_40)) {
2807      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2808         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
2809      } else {
2810         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
2811      }
2812   } else if(SiS_Pr->ChipType == XGI_20) {
2813      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2814         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
2815      } else {
2816         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
2817      }
2818      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
2819   }
2820#endif
2821}
2822
2823#ifdef CONFIG_FB_SIS_315
2824static void
2825SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
2826{
2827#if 0
2828   /* TODO: Find out about IOAddress2 */
2829   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
2830   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
2831   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
2832   int i;
2833
2834   if((SiS_Pr->ChipRevision != 0) ||
2835      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
2836      return;
2837
2838   for(i = 0; i <= 4; i++) {                                    /* SR00 - SR04 */
2839      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
2840   }
2841   for(i = 0; i <= 8; i++) {                                    /* GR00 - GR08 */
2842      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
2843   }
2844   SiS_SetReg(P2_3c4,0x05,0x86);
2845   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));   /* SR06 */
2846   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));   /* SR21 */
2847   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));     /* MISC */
2848   SiS_SetReg(P2_3c4,0x05,0x00);
2849#endif
2850}
2851#endif
2852
2853/*********************************************/
2854/*                 LOAD DAC                  */
2855/*********************************************/
2856
2857static void
2858SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
2859             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
2860{
2861   unsigned short d1, d2, d3;
2862
2863   switch(dl) {
2864   case  0: d1 = dh; d2 = ah; d3 = al; break;
2865   case  1: d1 = ah; d2 = al; d3 = dh; break;
2866   default: d1 = al; d2 = dh; d3 = ah;
2867   }
2868   SiS_SetRegByte(DACData, (d1 << shiftflag));
2869   SiS_SetRegByte(DACData, (d2 << shiftflag));
2870   SiS_SetRegByte(DACData, (d3 << shiftflag));
2871}
2872
2873void
2874SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2875{
2876   unsigned short data, data2, time, i, j, k, m, n, o;
2877   unsigned short si, di, bx, sf;
2878   SISIOADDRESS DACAddr, DACData;
2879   const unsigned char *table = NULL;
2880
2881   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
2882
2883   j = time = 64;
2884   if(data == 0x00)      table = SiS_MDA_DAC;
2885   else if(data == 0x08) table = SiS_CGA_DAC;
2886   else if(data == 0x10) table = SiS_EGA_DAC;
2887   else if(data == 0x18) {
2888      j = 16;
2889      time = 256;
2890      table = SiS_VGA_DAC;
2891   }
2892
2893   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
2894         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
2895       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
2896       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
2897      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
2898      DACAddr = SiS_Pr->SiS_P3c8;
2899      DACData = SiS_Pr->SiS_P3c9;
2900      sf = 0;
2901   } else {
2902      DACAddr = SiS_Pr->SiS_Part5Port;
2903      DACData = SiS_Pr->SiS_Part5Port + 1;
2904      sf = 2;
2905   }
2906
2907   SiS_SetRegByte(DACAddr,0x00);
2908
2909   for(i = 0; i < j; i++) {
2910      data = table[i];
2911      for(k = 0; k < 3; k++) {
2912        data2 = 0;
2913        if(data & 0x01) data2 += 0x2A;
2914        if(data & 0x02) data2 += 0x15;
2915        SiS_SetRegByte(DACData, (data2 << sf));
2916        data >>= 2;
2917      }
2918   }
2919
2920   if(time == 256) {
2921      for(i = 16; i < 32; i++) {
2922         data = table[i] << sf;
2923         for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
2924      }
2925      si = 32;
2926      for(m = 0; m < 9; m++) {
2927         di = si;
2928         bx = si + 4;
2929         for(n = 0; n < 3; n++) {
2930            for(o = 0; o < 5; o++) {
2931               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
2932               si++;
2933            }
2934            si -= 2;
2935            for(o = 0; o < 3; o++) {
2936               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
2937               si--;
2938            }
2939         }            /* for n < 3 */
2940         si += 5;
2941      }               /* for m < 9 */
2942   }
2943}
2944
2945/*********************************************/
2946/*         SET CRT1 REGISTER GROUP           */
2947/*********************************************/
2948
2949static void
2950SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2951{
2952   unsigned short StandTableIndex, RefreshRateTableIndex;
2953
2954   SiS_Pr->SiS_CRT1Mode = ModeNo;
2955
2956   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
2957
2958   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
2959      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
2960         SiS_DisableBridge(SiS_Pr);
2961      }
2962   }
2963
2964   SiS_ResetSegmentRegisters(SiS_Pr);
2965
2966   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
2967   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
2968   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
2969   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
2970   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
2971   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
2972   SiS_ResetCRT1VCLK(SiS_Pr);
2973
2974   SiS_Pr->SiS_SelectCRT2Rate = 0;
2975   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
2976
2977   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
2978      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2979         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2980      }
2981   }
2982
2983   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2984      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2985   }
2986
2987   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
2988
2989   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2990      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
2991   }
2992
2993   if(RefreshRateTableIndex != 0xFFFF) {
2994      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
2995      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2996      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2997      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2998   }
2999
3000   switch(SiS_Pr->ChipType) {
3001#ifdef CONFIG_FB_SIS_300
3002   case SIS_300:
3003      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
3004      break;
3005   case SIS_540:
3006   case SIS_630:
3007   case SIS_730:
3008      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
3009      break;
3010#endif
3011   default:
3012#ifdef CONFIG_FB_SIS_315
3013      if(SiS_Pr->ChipType == XGI_20) {
3014         unsigned char sr2b = 0, sr2c = 0;
3015         switch(ModeNo) {
3016         case 0x00:
3017         case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
3018         case 0x04:
3019         case 0x05:
3020         case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
3021         }
3022         if(sr2b) {
3023            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
3024            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
3025            SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
3026         }
3027      }
3028      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
3029#endif
3030      break;
3031   }
3032
3033   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3034
3035#ifdef CONFIG_FB_SIS_315
3036   if(SiS_Pr->ChipType == XGI_40) {
3037      SiS_SetupDualChip(SiS_Pr);
3038   }
3039#endif
3040
3041   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
3042
3043   if(SiS_Pr->SiS_flag_clearbuffer) {
3044      SiS_ClearBuffer(SiS_Pr, ModeNo);
3045   }
3046
3047   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
3048      SiS_WaitRetrace1(SiS_Pr);
3049      SiS_DisplayOn(SiS_Pr);
3050   }
3051}
3052
3053/*********************************************/
3054/*       HELPER: VIDEO BRIDGE PROG CLK       */
3055/*********************************************/
3056
3057static void
3058SiS_InitVB(struct SiS_Private *SiS_Pr)
3059{
3060   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3061
3062   SiS_Pr->Init_P4_0E = 0;
3063   if(SiS_Pr->SiS_ROMNew) {
3064      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
3065   } else if(SiS_Pr->ChipType >= XGI_40) {
3066      if(SiS_Pr->SiS_XGIROM) {
3067         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
3068      }
3069   }
3070}
3071
3072static void
3073SiS_ResetVB(struct SiS_Private *SiS_Pr)
3074{
3075#ifdef CONFIG_FB_SIS_315
3076   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
3077   unsigned short temp;
3078
3079   /* VB programming clock */
3080   if(SiS_Pr->SiS_UseROM) {
3081      if(SiS_Pr->ChipType < SIS_330) {
3082         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
3083         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3084         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3085      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
3086         temp = ROMAddr[0x7e] | 0x40;
3087         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3088         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3089      }
3090   } else if(SiS_Pr->ChipType >= XGI_40) {
3091      temp = 0x40;
3092      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
3093      /* Can we do this on any chipset? */
3094      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3095   }
3096#endif
3097}
3098
3099/*********************************************/
3100/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
3101/*********************************************/
3102
3103static void
3104SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3105{
3106   /* SiS65x and XGI set up some sort of "lock mode" for text
3107    * which locks CRT2 in some way to CRT1 timing. Disable
3108    * this here.
3109    */
3110#ifdef CONFIG_FB_SIS_315
3111   if((IS_SIS651) || (IS_SISM650) ||
3112      SiS_Pr->ChipType == SIS_340 ||
3113      SiS_Pr->ChipType == XGI_40) {
3114      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
3115      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
3116      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
3117      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
3118      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
3119   }
3120   /* !!! This does not support modes < 0x13 !!! */
3121#endif
3122}
3123
3124/*********************************************/
3125/*     HELPER: SET AGP TIMING FOR SiS760     */
3126/*********************************************/
3127
3128static void
3129SiS_Handle760(struct SiS_Private *SiS_Pr)
3130{
3131#ifdef CONFIG_FB_SIS_315
3132   unsigned int somebase;
3133   unsigned char temp1, temp2, temp3;
3134
3135   if( (SiS_Pr->ChipType != SIS_760)                         ||
3136       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
3137       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
3138       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
3139      return;
3140
3141   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
3142   somebase &= 0xffff;
3143
3144   if(somebase == 0) return;
3145
3146   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
3147
3148   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
3149      temp1 = 0x21;
3150      temp2 = 0x03;
3151      temp3 |= 0x08;
3152   } else {
3153      temp1 = 0x25;
3154      temp2 = 0x0b;
3155   }
3156
3157   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
3158   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
3159
3160   SiS_SetRegByte((somebase + 0x85), temp3);
3161#endif
3162}
3163
3164/*********************************************/
3165/*                 SiSSetMode()              */
3166/*********************************************/
3167
3168bool
3169SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3170{
3171   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3172   unsigned short RealModeNo, ModeIdIndex;
3173   unsigned char  backupreg = 0;
3174   unsigned short KeepLockReg;
3175
3176   SiS_Pr->UseCustomMode = false;
3177   SiS_Pr->CRT1UsesCustomMode = false;
3178
3179   SiS_Pr->SiS_flag_clearbuffer = 0;
3180
3181   if(SiS_Pr->UseCustomMode) {
3182      ModeNo = 0xfe;
3183   } else {
3184      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
3185      ModeNo &= 0x7f;
3186   }
3187
3188   /* Don't use FSTN mode for CRT1 */
3189   RealModeNo = ModeNo;
3190   if(ModeNo == 0x5b) ModeNo = 0x56;
3191
3192   SiSInitPtr(SiS_Pr);
3193   SiSRegInit(SiS_Pr, BaseAddr);
3194   SiS_GetSysFlags(SiS_Pr);
3195
3196   SiS_Pr->SiS_VGAINFO = 0x11;
3197
3198   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
3199   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3200
3201   SiSInitPCIetc(SiS_Pr);
3202   SiSSetLVDSetc(SiS_Pr);
3203   SiSDetermineROMUsage(SiS_Pr);
3204
3205   SiS_UnLockCRT2(SiS_Pr);
3206
3207   if(!SiS_Pr->UseCustomMode) {
3208      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3209   } else {
3210      ModeIdIndex = 0;
3211   }
3212
3213   SiS_GetVBType(SiS_Pr);
3214
3215   /* Init/restore some VB registers */
3216   SiS_InitVB(SiS_Pr);
3217   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3218      if(SiS_Pr->ChipType >= SIS_315H) {
3219         SiS_ResetVB(SiS_Pr);
3220         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3221         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3222         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3223      } else {
3224         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3225      }
3226   }
3227
3228   /* Get VB information (connectors, connected devices) */
3229   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
3230   SiS_SetYPbPr(SiS_Pr);
3231   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3232   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3233   SiS_SetLowModeTest(SiS_Pr, ModeNo);
3234
3235   /* Check memory size (kernel framebuffer driver only) */
3236   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
3237      return false;
3238   }
3239
3240   SiS_OpenCRTC(SiS_Pr);
3241
3242   if(SiS_Pr->UseCustomMode) {
3243      SiS_Pr->CRT1UsesCustomMode = true;
3244      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3245      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3246   } else {
3247      SiS_Pr->CRT1UsesCustomMode = false;
3248   }
3249
3250   /* Set mode on CRT1 */
3251   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
3252       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
3253      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3254   }
3255
3256   /* Set mode on CRT2 */
3257   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
3258      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
3259          (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
3260          (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
3261          (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3262         SiS_SetCRT2Group(SiS_Pr, RealModeNo);
3263      }
3264   }
3265
3266   SiS_HandleCRT1(SiS_Pr);
3267
3268   SiS_StrangeStuff(SiS_Pr);
3269
3270   SiS_DisplayOn(SiS_Pr);
3271   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3272
3273#ifdef CONFIG_FB_SIS_315
3274   if(SiS_Pr->ChipType >= SIS_315H) {
3275      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3276         if(!(SiS_IsDualEdge(SiS_Pr))) {
3277            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3278         }
3279      }
3280   }
3281#endif
3282
3283   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3284      if(SiS_Pr->ChipType >= SIS_315H) {
3285#ifdef CONFIG_FB_SIS_315
3286         if(!SiS_Pr->SiS_ROMNew) {
3287            if(SiS_IsVAMode(SiS_Pr)) {
3288               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3289            } else {
3290               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3291            }
3292         }
3293
3294         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3295
3296         if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
3297            if((ModeNo == 0x03) || (ModeNo == 0x10)) {
3298               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
3299               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
3300            }
3301         }
3302
3303         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3304            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3305         }
3306#endif
3307      } else if((SiS_Pr->ChipType == SIS_630) ||
3308                (SiS_Pr->ChipType == SIS_730)) {
3309         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3310      }
3311   }
3312
3313   SiS_CloseCRTC(SiS_Pr);
3314
3315   SiS_Handle760(SiS_Pr);
3316
3317   /* We never lock registers in XF86 */
3318   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
3319
3320   return true;
3321}
3322
3323#ifndef GETBITSTR
3324#define GENBITSMASK(mask)       GENMASK(1?mask,0?mask)
3325#define GETBITS(var,mask)       (((var) & GENBITSMASK(mask)) >> (0?mask))
3326#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
3327#endif
3328
3329void
3330SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
3331{
3332   int x = 1; /* Fix sync */
3333
3334   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;                /* CR0 */
3335   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;                       /* CR1 */
3336   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;                    /* CR2 */
3337   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;    /* CR3 */
3338   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;                     /* CR4 */
3339   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |   /* CR5 */
3340                            (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
3341
3342   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;                 /* CR6 */
3343   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)          /* CR7 */
3344                          | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
3345                          | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
3346                          | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
3347                          | 0x10
3348                          | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
3349                          | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
3350                          | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
3351
3352   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5);  /* CR9 */
3353
3354   if(depth != 8) {
3355      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;         /* SRE */
3356      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
3357   }
3358
3359   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;                   /* CR10 */
3360   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;           /* CR11 */
3361   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;                   /* CR12 */
3362   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;                   /* CR15 */
3363   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;                   /* CR16 */
3364
3365   SiS_Pr->CCRT1CRTC[13] =                                                      /* SRA */
3366                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
3367                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
3368                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
3369                        GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
3370                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
3371                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
3372
3373   SiS_Pr->CCRT1CRTC[14] =                                                      /* SRB */
3374                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
3375                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
3376                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
3377                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
3378
3379
3380   SiS_Pr->CCRT1CRTC[15] =                                                      /* SRC */
3381                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
3382                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
3383}
3384
3385void
3386SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3387                unsigned short ModeIdIndex)
3388{
3389   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
3390   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
3391   int i, j;
3392
3393   /* 1:1 data: use data set by setcrt1crtc() */
3394   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
3395
3396   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
3397
3398   if(modeflag & HalfDCLK) VGAHDE >>= 1;
3399
3400   SiS_Pr->CHDisplay = VGAHDE;
3401   SiS_Pr->CHBlankStart = VGAHDE;
3402
3403   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
3404   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
3405
3406   if(SiS_Pr->ChipType < SIS_315H) {
3407#ifdef CONFIG_FB_SIS_300
3408      tempbx = SiS_Pr->SiS_VGAHT;
3409      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3410         tempbx = SiS_Pr->PanelHT;
3411      }
3412      if(modeflag & HalfDCLK) tempbx >>= 1;
3413      remaining = tempbx % 8;
3414#endif
3415   } else {
3416#ifdef CONFIG_FB_SIS_315
3417      /* OK for LCDA, LVDS */
3418      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
3419      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
3420      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3421         tempax = SiS_Pr->PanelXRes;
3422      }
3423      tempbx += tempax;
3424      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
3425#endif
3426   }
3427   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
3428
3429   if(SiS_Pr->ChipType < SIS_315H) {
3430#ifdef CONFIG_FB_SIS_300
3431      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
3432         SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
3433         SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
3434         if(modeflag & HalfDCLK) {
3435            SiS_Pr->CHSyncStart >>= 1;
3436            SiS_Pr->CHSyncEnd >>= 1;
3437         }
3438      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3439         tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
3440         tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
3441         if(modeflag & HalfDCLK) {
3442            tempax >>= 1;
3443            tempbx >>= 1;
3444         }
3445         SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
3446         tempax = SiS_Pr->PanelHRE + 7;
3447         if(modeflag & HalfDCLK) tempax >>= 1;
3448         SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
3449      } else {
3450         SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
3451         if(modeflag & HalfDCLK) {
3452            SiS_Pr->CHSyncStart >>= 1;
3453            tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
3454            SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
3455         } else {
3456            SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
3457            SiS_Pr->CHSyncStart += 8;
3458         }
3459      }
3460#endif
3461   } else {
3462#ifdef CONFIG_FB_SIS_315
3463      tempax = VGAHDE;
3464      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3465         tempbx = SiS_Pr->PanelXRes;
3466         if(modeflag & HalfDCLK) tempbx >>= 1;
3467         tempax += ((tempbx - tempax) >> 1);
3468      }
3469      tempax += SiS_Pr->PanelHRS;
3470      SiS_Pr->CHSyncStart = tempax;
3471      tempax += SiS_Pr->PanelHRE;
3472      SiS_Pr->CHSyncEnd = tempax;
3473#endif
3474   }
3475
3476   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
3477   tempax = SiS_Pr->SiS_VGAVDE;
3478   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3479      tempax = SiS_Pr->PanelYRes;
3480   } else if(SiS_Pr->ChipType < SIS_315H) {
3481#ifdef CONFIG_FB_SIS_300
3482      /* Stupid hack for 640x400/320x200 */
3483      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3484         if((tempax + tempbx) == 438) tempbx += 16;
3485      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
3486                (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
3487         tempax = 0;
3488         tempbx = SiS_Pr->SiS_VGAVT;
3489      }
3490#endif
3491   }
3492   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
3493
3494   tempax = SiS_Pr->SiS_VGAVDE;
3495   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3496      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
3497   }
3498   tempax += SiS_Pr->PanelVRS;
3499   SiS_Pr->CVSyncStart = tempax;
3500   tempax += SiS_Pr->PanelVRE;
3501   SiS_Pr->CVSyncEnd = tempax;
3502   if(SiS_Pr->ChipType < SIS_315H) {
3503      SiS_Pr->CVSyncStart--;
3504      SiS_Pr->CVSyncEnd--;
3505   }
3506
3507   SiS_CalcCRRegisters(SiS_Pr, 8);
3508   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
3509   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
3510   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
3511
3512   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
3513
3514   for(i = 0, j = 0; i <= 7; i++, j++) {
3515      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3516   }
3517   for(j = 0x10; i <= 10; i++, j++) {
3518      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3519   }
3520   for(j = 0x15; i <= 12; i++, j++) {
3521      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3522   }
3523   for(j = 0x0A; i <= 15; i++, j++) {
3524      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
3525   }
3526
3527   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
3528   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
3529
3530   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
3531   if(modeflag & DoubleScanMode) tempax |= 0x80;
3532   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
3533
3534}
3535
3536void
3537SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
3538                        int xres, int yres,
3539                        struct fb_var_screeninfo *var, bool writeres
3540)
3541{
3542   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
3543   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
3544   unsigned char  sr_data, cr_data, cr_data2;
3545   int            A, B, C, D, E, F, temp;
3546
3547   sr_data = crdata[14];
3548
3549   /* Horizontal total */
3550   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
3551   A = HT + 5;
3552
3553   /* Horizontal display enable end */
3554   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
3555   E = HDE + 1;
3556
3557   /* Horizontal retrace (=sync) start */
3558   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
3559   F = HRS - E - 3;
3560
3561   /* Horizontal blank start */
3562   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
3563
3564   sr_data = crdata[15];
3565   cr_data = crdata[5];
3566
3567   /* Horizontal blank end */
3568   HBE = (crdata[3] & 0x1f) |
3569         ((unsigned short)(cr_data & 0x80) >> 2) |
3570         ((unsigned short)(sr_data & 0x03) << 6);
3571
3572   /* Horizontal retrace (=sync) end */
3573   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
3574
3575   temp = HBE - ((E - 1) & 255);
3576   B = (temp > 0) ? temp : (temp + 256);
3577
3578   temp = HRE - ((E + F + 3) & 63);
3579   C = (temp > 0) ? temp : (temp + 64);
3580
3581   D = B - F - C;
3582
3583   if(writeres) var->xres = xres = E * 8;
3584   var->left_margin = D * 8;
3585   var->right_margin = F * 8;
3586   var->hsync_len = C * 8;
3587
3588   /* Vertical */
3589   sr_data = crdata[13];
3590   cr_data = crdata[7];
3591
3592   /* Vertical total */
3593   VT  = crdata[6] |
3594         ((unsigned short)(cr_data & 0x01) << 8) |
3595         ((unsigned short)(cr_data & 0x20) << 4) |
3596         ((unsigned short)(sr_data & 0x01) << 10);
3597   A = VT + 2;
3598
3599   /* Vertical display enable end */
3600   VDE = crdata[10] |
3601         ((unsigned short)(cr_data & 0x02) << 7) |
3602         ((unsigned short)(cr_data & 0x40) << 3) |
3603         ((unsigned short)(sr_data & 0x02) << 9);
3604   E = VDE + 1;
3605
3606   /* Vertical retrace (=sync) start */
3607   VRS = crdata[8] |
3608         ((unsigned short)(cr_data & 0x04) << 6) |
3609         ((unsigned short)(cr_data & 0x80) << 2) |
3610         ((unsigned short)(sr_data & 0x08) << 7);
3611   F = VRS + 1 - E;
3612
3613   cr_data2 = (crdata[16] & 0x01) << 5;
3614
3615   /* Vertical blank start */
3616   VBS = crdata[11] |
3617         ((unsigned short)(cr_data  & 0x08) << 5) |
3618         ((unsigned short)(cr_data2 & 0x20) << 4) |
3619         ((unsigned short)(sr_data  & 0x04) << 8);
3620
3621   /* Vertical blank end */
3622   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
3623   temp = VBE - ((E - 1) & 511);
3624   B = (temp > 0) ? temp : (temp + 512);
3625
3626   /* Vertical retrace (=sync) end */
3627   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
3628   temp = VRE - ((E + F - 1) & 31);
3629   C = (temp > 0) ? temp : (temp + 32);
3630
3631   D = B - F - C;
3632
3633   if(writeres) var->yres = yres = E;
3634   var->upper_margin = D;
3635   var->lower_margin = F;
3636   var->vsync_len = C;
3637
3638   if((xres == 320) && ((yres == 200) || (yres == 240))) {
3639        /* Terrible hack, but correct CRTC data for
3640         * these modes only produces a black screen...
3641         * (HRE is 0, leading into a too large C and
3642         * a negative D. The CRT controller does not
3643         * seem to like correcting HRE to 50)
3644         */
3645      var->left_margin = (400 - 376);
3646      var->right_margin = (328 - 320);
3647      var->hsync_len = (376 - 328);
3648
3649   }
3650
3651}
3652
3653
3654
3655
3656