linux/drivers/video/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             case 768:
 655                if(VGAEngine == SIS_300_VGA) {
 656                   ModeIndex = ModeIndex_300_1280x768[Depth];
 657                } else {
 658                   ModeIndex = ModeIndex_310_1280x768[Depth];
 659                }
 660                break;
 661             case 800:
 662                if(VGAEngine == SIS_315_VGA) {
 663                   ModeIndex = ModeIndex_1280x800[Depth];
 664                }
 665                break;
 666             case 854:
 667                if(VGAEngine == SIS_315_VGA) {
 668                   ModeIndex = ModeIndex_1280x854[Depth];
 669                }
 670                break;
 671             case 960:
 672                ModeIndex = ModeIndex_1280x960[Depth];
 673                break;
 674             case 1024:
 675                ModeIndex = ModeIndex_1280x1024[Depth];
 676                break;
 677             }
 678             break;
 679        case 1360:
 680             if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
 681                if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
 682             }
 683             break;
 684        case 1400:
 685             if(VGAEngine == SIS_315_VGA) {
 686                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 687                   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
 688                }
 689             }
 690             break;
 691        case 1600:
 692             if(VGAEngine == SIS_315_VGA) {
 693                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 694                   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
 695                }
 696             }
 697             break;
 698#ifndef VB_FORBID_CRT2LCD_OVER_1600
 699        case 1680:
 700             if(VGAEngine == SIS_315_VGA) {
 701                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 702                   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
 703                }
 704             }
 705             break;
 706        case 1920:
 707             if(VGAEngine == SIS_315_VGA) {
 708                if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
 709                   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
 710                }
 711             }
 712             break;
 713        case 2048:
 714             if(VGAEngine == SIS_315_VGA) {
 715                if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
 716                   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
 717                }
 718             }
 719             break;
 720#endif
 721      }
 722   }
 723
 724   return ModeIndex;
 725}
 726
 727unsigned short
 728SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
 729                        unsigned int VBFlags2)
 730{
 731   unsigned short ModeIndex = 0;
 732
 733   if(VBFlags2 & VB2_CHRONTEL) {
 734
 735      switch(HDisplay)
 736      {
 737        case 512:
 738             if(VGAEngine == SIS_315_VGA) {
 739                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 740             }
 741             break;
 742        case 640:
 743             if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 744             else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 745             break;
 746        case 800:
 747             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 748             break;
 749        case 1024:
 750             if(VGAEngine == SIS_315_VGA) {
 751                if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
 752             }
 753             break;
 754      }
 755
 756   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
 757
 758      switch(HDisplay)
 759      {
 760        case 320:
 761             if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
 762             else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
 763             break;
 764        case 400:
 765             if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 766             break;
 767        case 512:
 768             if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
 769                 (VBFlags & TV_HIVISION)                                              ||
 770                 ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 771                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 772             }
 773             break;
 774        case 640:
 775             if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 776             else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 777             break;
 778        case 720:
 779             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
 780                if(VDisplay == 480) {
 781                   ModeIndex = ModeIndex_720x480[Depth];
 782                } else if(VDisplay == 576) {
 783                   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
 784                       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
 785                      ModeIndex = ModeIndex_720x576[Depth];
 786                }
 787             }
 788             break;
 789        case 768:
 790             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
 791                if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
 792                    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 793                   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 794                }
 795             }
 796             break;
 797        case 800:
 798             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 799             else if(VDisplay == 480) {
 800                if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
 801                   ModeIndex = ModeIndex_800x480[Depth];
 802                }
 803             }
 804             break;
 805        case 960:
 806             if(VGAEngine == SIS_315_VGA) {
 807                if(VDisplay == 600) {
 808                   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 809                      ModeIndex = ModeIndex_960x600[Depth];
 810                   }
 811                }
 812             }
 813             break;
 814        case 1024:
 815             if(VDisplay == 768) {
 816                if(VBFlags2 & VB2_30xBLV) {
 817                   ModeIndex = ModeIndex_1024x768[Depth];
 818                }
 819             } else if(VDisplay == 576) {
 820                if( (VBFlags & TV_HIVISION) ||
 821                    ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
 822                    ((VBFlags2 & VB2_30xBLV) &&
 823                     ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
 824                   ModeIndex = ModeIndex_1024x576[Depth];
 825                }
 826             }
 827             break;
 828        case 1280:
 829             if(VDisplay == 720) {
 830                if((VBFlags & TV_HIVISION) ||
 831                   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
 832                   ModeIndex = ModeIndex_1280x720[Depth];
 833                }
 834             } else if(VDisplay == 1024) {
 835                if((VBFlags & TV_HIVISION) ||
 836                   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 837                   ModeIndex = ModeIndex_1280x1024[Depth];
 838                }
 839             }
 840             break;
 841      }
 842   }
 843   return ModeIndex;
 844}
 845
 846unsigned short
 847SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
 848                        unsigned int VBFlags2)
 849{
 850   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
 851
 852   if(HDisplay >= 1920) return 0;
 853
 854   switch(HDisplay)
 855   {
 856        case 1600:
 857                if(VDisplay == 1200) {
 858                        if(VGAEngine != SIS_315_VGA) return 0;
 859                        if(!(VBFlags2 & VB2_30xB)) return 0;
 860                }
 861                break;
 862        case 1680:
 863                if(VDisplay == 1050) {
 864                        if(VGAEngine != SIS_315_VGA) return 0;
 865                        if(!(VBFlags2 & VB2_30xB)) return 0;
 866                }
 867                break;
 868   }
 869
 870   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
 871}
 872
 873
 874/*********************************************/
 875/*          HELPER: SetReg, GetReg           */
 876/*********************************************/
 877
 878void
 879SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
 880{
 881        outb(index, port);
 882        outb(data, port + 1);
 883}
 884
 885void
 886SiS_SetRegByte(SISIOADDRESS port, u8 data)
 887{
 888        outb(data, port);
 889}
 890
 891void
 892SiS_SetRegShort(SISIOADDRESS port, u16 data)
 893{
 894        outw(data, port);
 895}
 896
 897void
 898SiS_SetRegLong(SISIOADDRESS port, u32 data)
 899{
 900        outl(data, port);
 901}
 902
 903u8
 904SiS_GetReg(SISIOADDRESS port, u8 index)
 905{
 906        outb(index, port);
 907        return inb(port + 1);
 908}
 909
 910u8
 911SiS_GetRegByte(SISIOADDRESS port)
 912{
 913        return inb(port);
 914}
 915
 916u16
 917SiS_GetRegShort(SISIOADDRESS port)
 918{
 919        return inw(port);
 920}
 921
 922u32
 923SiS_GetRegLong(SISIOADDRESS port)
 924{
 925        return inl(port);
 926}
 927
 928void
 929SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
 930{
 931   u8 temp;
 932
 933   temp = SiS_GetReg(Port, Index);
 934   temp = (temp & (DataAND)) | DataOR;
 935   SiS_SetReg(Port, Index, temp);
 936}
 937
 938void
 939SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
 940{
 941   u8 temp;
 942
 943   temp = SiS_GetReg(Port, Index);
 944   temp &= DataAND;
 945   SiS_SetReg(Port, Index, temp);
 946}
 947
 948void
 949SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
 950{
 951   u8 temp;
 952
 953   temp = SiS_GetReg(Port, Index);
 954   temp |= DataOR;
 955   SiS_SetReg(Port, Index, temp);
 956}
 957
 958/*********************************************/
 959/*      HELPER: DisplayOn, DisplayOff        */
 960/*********************************************/
 961
 962void
 963SiS_DisplayOn(struct SiS_Private *SiS_Pr)
 964{
 965   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 966}
 967
 968void
 969SiS_DisplayOff(struct SiS_Private *SiS_Pr)
 970{
 971   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 972}
 973
 974
 975/*********************************************/
 976/*        HELPER: Init Port Addresses        */
 977/*********************************************/
 978
 979void
 980SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
 981{
 982   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
 983   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
 984   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
 985   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
 986   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
 987   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
 988   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
 989   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
 990   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
 991   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
 992   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
 993   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
 994   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
 995   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
 996   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
 997   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
 998   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
 999   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
1000   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
1001   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
1002   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
1003   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
1004}
1005
1006/*********************************************/
1007/*             HELPER: GetSysFlags           */
1008/*********************************************/
1009
1010static void
1011SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
1012{
1013   unsigned char cr5f, temp1, temp2;
1014
1015   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
1016   /* (SR11 is used for DDC and in enable/disablebridge) */
1017   SiS_Pr->SiS_SensibleSR11 = false;
1018   SiS_Pr->SiS_MyCR63 = 0x63;
1019   if(SiS_Pr->ChipType >= SIS_330) {
1020      SiS_Pr->SiS_MyCR63 = 0x53;
1021      if(SiS_Pr->ChipType >= SIS_661) {
1022         SiS_Pr->SiS_SensibleSR11 = true;
1023      }
1024   }
1025
1026   /* You should use the macros, not these flags directly */
1027
1028   SiS_Pr->SiS_SysFlags = 0;
1029   if(SiS_Pr->ChipType == SIS_650) {
1030      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
1031      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
1032      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1033      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
1034      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1035      if((!temp1) || (temp2)) {
1036         switch(cr5f) {
1037            case 0x80:
1038            case 0x90:
1039            case 0xc0:
1040               SiS_Pr->SiS_SysFlags |= SF_IsM650;
1041               break;
1042            case 0xa0:
1043            case 0xb0:
1044            case 0xe0:
1045               SiS_Pr->SiS_SysFlags |= SF_Is651;
1046               break;
1047         }
1048      } else {
1049         switch(cr5f) {
1050            case 0x90:
1051               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1052               switch(temp1) {
1053                  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
1054                  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
1055                  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
1056               }
1057               break;
1058            case 0xb0:
1059               SiS_Pr->SiS_SysFlags |= SF_Is652;
1060               break;
1061            default:
1062               SiS_Pr->SiS_SysFlags |= SF_IsM650;
1063               break;
1064         }
1065      }
1066   }
1067
1068   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
1069      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
1070         SiS_Pr->SiS_SysFlags |= SF_760LFB;
1071      }
1072      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
1073         SiS_Pr->SiS_SysFlags |= SF_760UMA;
1074      }
1075   }
1076}
1077
1078/*********************************************/
1079/*         HELPER: Init PCI & Engines        */
1080/*********************************************/
1081
1082static void
1083SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1084{
1085   switch(SiS_Pr->ChipType) {
1086#ifdef CONFIG_FB_SIS_300
1087   case SIS_300:
1088   case SIS_540:
1089   case SIS_630:
1090   case SIS_730:
1091      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
1092       *     - RELOCATED VGA IO ENABLED (0x20)
1093       *     - MMIO ENABLED (0x01)
1094       * Leave other bits untouched.
1095       */
1096      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1097      /*  - Enable 2D (0x40)
1098       *  - Enable 3D (0x02)
1099       *  - Enable 3D Vertex command fetch (0x10) ?
1100       *  - Enable 3D command parser (0x08) ?
1101       */
1102      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
1103      break;
1104#endif
1105#ifdef CONFIG_FB_SIS_315
1106   case SIS_315H:
1107   case SIS_315:
1108   case SIS_315PRO:
1109   case SIS_650:
1110   case SIS_740:
1111   case SIS_330:
1112   case SIS_661:
1113   case SIS_741:
1114   case SIS_660:
1115   case SIS_760:
1116   case SIS_761:
1117   case SIS_340:
1118   case XGI_40:
1119      /* See above */
1120      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1121      /*  - Enable 3D G/L transformation engine (0x80)
1122       *  - Enable 2D (0x40)
1123       *  - Enable 3D vertex command fetch (0x10)
1124       *  - Enable 3D command parser (0x08)
1125       *  - Enable 3D (0x02)
1126       */
1127      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
1128      break;
1129   case XGI_20:
1130   case SIS_550:
1131      /* See above */
1132      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1133      /* No 3D engine ! */
1134      /*  - Enable 2D (0x40)
1135       *  - disable 3D
1136       */
1137      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
1138      break;
1139#endif
1140   default:
1141      break;
1142   }
1143}
1144
1145/*********************************************/
1146/*             HELPER: SetLVDSetc            */
1147/*********************************************/
1148
1149static
1150void
1151SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1152{
1153   unsigned short temp;
1154
1155   SiS_Pr->SiS_IF_DEF_LVDS = 0;
1156   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
1157   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
1158   SiS_Pr->SiS_IF_DEF_CONEX = 0;
1159
1160   SiS_Pr->SiS_ChrontelInit = 0;
1161
1162   if(SiS_Pr->ChipType == XGI_20) return;
1163
1164   /* Check for SiS30x first */
1165   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1166   if((temp == 1) || (temp == 2)) return;
1167
1168   switch(SiS_Pr->ChipType) {
1169#ifdef CONFIG_FB_SIS_300
1170   case SIS_540:
1171   case SIS_630:
1172   case SIS_730:
1173        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1174        if((temp >= 2) && (temp <= 5))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1175        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
1176        if((temp == 4) || (temp == 5)) {
1177                /* Save power status (and error check) - UNUSED */
1178                SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
1179                SiS_Pr->SiS_IF_DEF_CH70xx = 1;
1180        }
1181        break;
1182#endif
1183#ifdef CONFIG_FB_SIS_315
1184   case SIS_550:
1185   case SIS_650:
1186   case SIS_740:
1187   case SIS_330:
1188        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1189        if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1190        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1191        break;
1192   case SIS_661:
1193   case SIS_741:
1194   case SIS_660:
1195   case SIS_760:
1196   case SIS_761:
1197   case SIS_340:
1198   case XGI_20:
1199   case XGI_40:
1200        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
1201        if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1202        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1203        if(temp == 4)                   SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
1204        break;
1205#endif
1206   default:
1207        break;
1208   }
1209}
1210
1211/*********************************************/
1212/*          HELPER: Enable DSTN/FSTN         */
1213/*********************************************/
1214
1215void
1216SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
1217{
1218   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
1219}
1220
1221void
1222SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
1223{
1224   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
1225}
1226
1227/*********************************************/
1228/*            HELPER: Get modeflag           */
1229/*********************************************/
1230
1231unsigned short
1232SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1233                unsigned short ModeIdIndex)
1234{
1235   if(SiS_Pr->UseCustomMode) {
1236      return SiS_Pr->CModeFlag;
1237   } else if(ModeNo <= 0x13) {
1238      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1239   } else {
1240      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1241   }
1242}
1243
1244/*********************************************/
1245/*        HELPER: Determine ROM usage        */
1246/*********************************************/
1247
1248bool
1249SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
1250{
1251   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
1252   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
1253
1254   if(SiS_Pr->ChipType >= XGI_20) {
1255      /* XGI ROMs don't qualify */
1256      return false;
1257   } else if(SiS_Pr->ChipType >= SIS_761) {
1258      /* I very much assume 761, 340 and newer will use new layout */
1259      return true;
1260   } else if(SiS_Pr->ChipType >= SIS_661) {
1261      if((ROMAddr[0x1a] == 'N') &&
1262         (ROMAddr[0x1b] == 'e') &&
1263         (ROMAddr[0x1c] == 'w') &&
1264         (ROMAddr[0x1d] == 'V')) {
1265         return true;
1266      }
1267      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
1268      if(romversoffs) {
1269         if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
1270            romvmaj = ROMAddr[romversoffs] - '0';
1271            romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
1272         }
1273      }
1274      if((romvmaj != 0) || (romvmin >= 92)) {
1275         return true;
1276      }
1277   } else if(IS_SIS650740) {
1278      if((ROMAddr[0x1a] == 'N') &&
1279         (ROMAddr[0x1b] == 'e') &&
1280         (ROMAddr[0x1c] == 'w') &&
1281         (ROMAddr[0x1d] == 'V')) {
1282         return true;
1283      }
1284   }
1285   return false;
1286}
1287
1288static void
1289SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
1290{
1291   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
1292   unsigned short romptr = 0;
1293
1294   SiS_Pr->SiS_UseROM = false;
1295   SiS_Pr->SiS_ROMNew = false;
1296   SiS_Pr->SiS_PWDOffset = 0;
1297
1298   if(SiS_Pr->ChipType >= XGI_20) return;
1299
1300   if((ROMAddr) && (SiS_Pr->UseROM)) {
1301      if(SiS_Pr->ChipType == SIS_300) {
1302         /* 300: We check if the code starts below 0x220 by
1303          * checking the jmp instruction at the beginning
1304          * of the BIOS image.
1305          */
1306         if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
1307            SiS_Pr->SiS_UseROM = true;
1308      } else if(SiS_Pr->ChipType < SIS_315H) {
1309         /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
1310          * the others do as well
1311          */
1312         SiS_Pr->SiS_UseROM = true;
1313      } else {
1314         /* 315/330 series stick to the standard(s) */
1315         SiS_Pr->SiS_UseROM = true;
1316         if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
1317            SiS_Pr->SiS_EMIOffset = 14;
1318            SiS_Pr->SiS_PWDOffset = 17;
1319            SiS_Pr->SiS661LCD2TableSize = 36;
1320            /* Find out about LCD data table entry size */
1321            if((romptr = SISGETROMW(0x0102))) {
1322               if(ROMAddr[romptr + (32 * 16)] == 0xff)
1323                  SiS_Pr->SiS661LCD2TableSize = 32;
1324               else if(ROMAddr[romptr + (34 * 16)] == 0xff)
1325                  SiS_Pr->SiS661LCD2TableSize = 34;
1326               else if(ROMAddr[romptr + (36 * 16)] == 0xff)        /* 0.94, 2.05.00+ */
1327                  SiS_Pr->SiS661LCD2TableSize = 36;
1328               else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
1329                        (ROMAddr[0x6F] & 0x01) ) {                 /* 2.03.00 - <2.05.00 */
1330                  SiS_Pr->SiS661LCD2TableSize = 38;                /* UMC data layout abandoned at 2.05.00 */
1331                  SiS_Pr->SiS_EMIOffset = 16;
1332                  SiS_Pr->SiS_PWDOffset = 19;
1333               }
1334            }
1335         }
1336      }
1337   }
1338}
1339
1340/*********************************************/
1341/*        HELPER: SET SEGMENT REGISTERS      */
1342/*********************************************/
1343
1344static void
1345SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
1346{
1347   unsigned short temp;
1348
1349   value &= 0x00ff;
1350   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
1351   temp |= (value >> 4);
1352   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1353   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
1354   temp |= (value & 0x0f);
1355   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1356}
1357
1358static void
1359SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
1360{
1361   unsigned short temp;
1362
1363   value &= 0x00ff;
1364   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
1365   temp |= (value & 0xf0);
1366   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1367   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
1368   temp |= (value << 4);
1369   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1370}
1371
1372static void
1373SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
1374{
1375   SiS_SetSegRegLower(SiS_Pr, value);
1376   SiS_SetSegRegUpper(SiS_Pr, value);
1377}
1378
1379static void
1380SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
1381{
1382   SiS_SetSegmentReg(SiS_Pr, 0);
1383}
1384
1385static void
1386SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
1387{
1388   unsigned short temp = value >> 8;
1389
1390   temp &= 0x07;
1391   temp |= (temp << 4);
1392   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
1393   SiS_SetSegmentReg(SiS_Pr, value);
1394}
1395
1396static void
1397SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
1398{
1399   SiS_SetSegmentRegOver(SiS_Pr, 0);
1400}
1401
1402static void
1403SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
1404{
1405   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
1406      SiS_ResetSegmentReg(SiS_Pr);
1407      SiS_ResetSegmentRegOver(SiS_Pr);
1408   }
1409}
1410
1411/*********************************************/
1412/*             HELPER: GetVBType             */
1413/*********************************************/
1414
1415static
1416void
1417SiS_GetVBType(struct SiS_Private *SiS_Pr)
1418{
1419   unsigned short flag = 0, rev = 0, nolcd = 0;
1420   unsigned short p4_0f, p4_25, p4_27;
1421
1422   SiS_Pr->SiS_VBType = 0;
1423
1424   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
1425      return;
1426
1427   if(SiS_Pr->ChipType == XGI_20)
1428      return;
1429
1430   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1431
1432   if(flag > 3)
1433      return;
1434
1435   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
1436
1437   if(flag >= 2) {
1438      SiS_Pr->SiS_VBType = VB_SIS302B;
1439   } else if(flag == 1) {
1440      if(rev >= 0xC0) {
1441         SiS_Pr->SiS_VBType = VB_SIS301C;
1442      } else if(rev >= 0xB0) {
1443         SiS_Pr->SiS_VBType = VB_SIS301B;
1444         /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
1445         nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
1446         if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
1447      } else {
1448         SiS_Pr->SiS_VBType = VB_SIS301;
1449      }
1450   }
1451   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
1452      if(rev >= 0xE0) {
1453         flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
1454         if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
1455         else             SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
1456      } else if(rev >= 0xD0) {
1457         SiS_Pr->SiS_VBType = VB_SIS301LV;
1458      }
1459   }
1460   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
1461      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
1462      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
1463      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
1464      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
1465      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
1466      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
1467      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
1468         SiS_Pr->SiS_VBType |= VB_UMC;
1469      }
1470      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
1471      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
1472      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
1473   }
1474}
1475
1476/*********************************************/
1477/*           HELPER: Check RAM size          */
1478/*********************************************/
1479
1480static bool
1481SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1482                unsigned short ModeIdIndex)
1483{
1484   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
1485   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1486   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
1487
1488   if(!AdapterMemSize) return true;
1489
1490   if(AdapterMemSize < memorysize) return false;
1491   return true;
1492}
1493
1494/*********************************************/
1495/*           HELPER: Get DRAM type           */
1496/*********************************************/
1497
1498#ifdef CONFIG_FB_SIS_315
1499static unsigned char
1500SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
1501{
1502   unsigned char data;
1503
1504   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
1505      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
1506   } else {
1507      if(SiS_Pr->ChipType >= XGI_20) {
1508         /* Do I need this? SR17 seems to be zero anyway... */
1509         data = 0;
1510      } else if(SiS_Pr->ChipType >= SIS_340) {
1511         /* TODO */
1512         data = 0;
1513      } if(SiS_Pr->ChipType >= SIS_661) {
1514         if(SiS_Pr->SiS_ROMNew) {
1515            data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
1516         } else {
1517            data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
1518         }
1519      } else if(IS_SIS550650740) {
1520         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
1521      } else {  /* 315, 330 */
1522         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
1523         if(SiS_Pr->ChipType == SIS_330) {
1524            if(data > 1) {
1525               switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
1526               case 0x00: data = 1; break;
1527               case 0x10: data = 3; break;
1528               case 0x20: data = 3; break;
1529               case 0x30: data = 2; break;
1530               }
1531            } else {
1532               data = 0;
1533            }
1534         }
1535      }
1536   }
1537
1538   return data;
1539}
1540
1541static unsigned short
1542SiS_GetMCLK(struct SiS_Private *SiS_Pr)
1543{
1544   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
1545   unsigned short index;
1546
1547   index = SiS_Get310DRAMType(SiS_Pr);
1548   if(SiS_Pr->ChipType >= SIS_661) {
1549      if(SiS_Pr->SiS_ROMNew) {
1550         return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
1551      }
1552      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1553   } else if(index >= 4) {
1554      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
1555   } else {
1556      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1557   }
1558}
1559#endif
1560
1561/*********************************************/
1562/*           HELPER: ClearBuffer             */
1563/*********************************************/
1564
1565static void
1566SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1567{
1568   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
1569   unsigned int   memsize = SiS_Pr->VideoMemorySize;
1570   unsigned short SISIOMEMTYPE *pBuffer;
1571   int i;
1572
1573   if(!memaddr || !memsize) return;
1574
1575   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
1576      if(ModeNo > 0x13) {
1577         memset_io(memaddr, 0, memsize);
1578      } else {
1579         pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1580         for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
1581      }
1582   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
1583      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1584      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
1585   } else {
1586      memset_io(memaddr, 0, 0x8000);
1587   }
1588}
1589
1590/*********************************************/
1591/*           HELPER: SearchModeID            */
1592/*********************************************/
1593
1594bool
1595SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
1596                unsigned short *ModeIdIndex)
1597{
1598   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
1599
1600   if((*ModeNo) <= 0x13) {
1601
1602      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
1603
1604      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1605         if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
1606         if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
1607      }
1608
1609      if((*ModeNo) == 0x07) {
1610          if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
1611          /* else 350 lines */
1612      }
1613      if((*ModeNo) <= 0x03) {
1614         if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
1615         if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
1616         /* else 350 lines  */
1617      }
1618      /* else 200 lines  */
1619
1620   } else {
1621
1622      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1623         if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
1624         if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
1625      }
1626
1627   }
1628   return true;
1629}
1630
1631/*********************************************/
1632/*            HELPER: GetModePtr             */
1633/*********************************************/
1634
1635unsigned short
1636SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1637{
1638   unsigned short index;
1639
1640   if(ModeNo <= 0x13) {
1641      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
1642   } else {
1643      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
1644      else index = 0x0F;
1645   }
1646   return index;
1647}
1648
1649/*********************************************/
1650/*         HELPERS: Get some indices         */
1651/*********************************************/
1652
1653unsigned short
1654SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
1655{
1656   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
1657      if(UseWide == 1) {
1658         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
1659      } else {
1660         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
1661      }
1662   } else {
1663      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
1664   }
1665}
1666
1667unsigned short
1668SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
1669{
1670   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
1671      if(UseWide == 1) {
1672         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
1673      } else {
1674         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
1675      }
1676   } else {
1677      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
1678   }
1679}
1680
1681/*********************************************/
1682/*           HELPER: LowModeTests            */
1683/*********************************************/
1684
1685static bool
1686SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1687{
1688   unsigned short temp, temp1, temp2;
1689
1690   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
1691      return true;
1692   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
1693   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
1694   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1695   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
1696   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1697   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
1698   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
1699   if((SiS_Pr->ChipType >= SIS_315H) ||
1700      (SiS_Pr->ChipType == SIS_300)) {
1701      if(temp2 == 0x55) return false;
1702      else return true;
1703   } else {
1704      if(temp2 != 0x55) return true;
1705      else {
1706         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
1707         return false;
1708      }
1709   }
1710}
1711
1712static void
1713SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1714{
1715   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
1716      SiS_Pr->SiS_SetFlag |= LowModeTests;
1717   }
1718}
1719
1720/*********************************************/
1721/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
1722/*********************************************/
1723
1724static void
1725SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
1726{
1727   if(IS_SIS650) {
1728      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1729      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
1730      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1731   } else if(IS_SIS661741660760) {
1732      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
1733      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1734      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1735      if(!SiS_Pr->SiS_ROMNew) {
1736         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
1737      }
1738   }
1739}
1740
1741static void
1742SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
1743{
1744#if 0 /* This locks some CRTC registers. We don't want that. */
1745   unsigned short temp1 = 0, temp2 = 0;
1746
1747   if(IS_SIS661741660760) {
1748      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1749         temp1 = 0xa0; temp2 = 0x08;
1750      }
1751      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
1752      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
1753   }
1754#endif
1755}
1756
1757static void
1758SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
1759{
1760   /* Enable CRT1 gating */
1761   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
1762#if 0
1763   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
1764      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
1765         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
1766         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
1767      }
1768   }
1769#endif
1770}
1771
1772/*********************************************/
1773/*           HELPER: GetColorDepth           */
1774/*********************************************/
1775
1776unsigned short
1777SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1778                unsigned short ModeIdIndex)
1779{
1780   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
1781   unsigned short modeflag;
1782   short index;
1783
1784   /* Do NOT check UseCustomMode, will skrew up FIFO */
1785   if(ModeNo == 0xfe) {
1786      modeflag = SiS_Pr->CModeFlag;
1787   } else if(ModeNo <= 0x13) {
1788      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1789   } else {
1790      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1791   }
1792
1793   index = (modeflag & ModeTypeMask) - ModeEGA;
1794   if(index < 0) index = 0;
1795   return ColorDepth[index];
1796}
1797
1798/*********************************************/
1799/*             HELPER: GetOffset             */
1800/*********************************************/
1801
1802unsigned short
1803SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1804                unsigned short ModeIdIndex, unsigned short RRTI)
1805{
1806   unsigned short xres, temp, colordepth, infoflag;
1807
1808   if(SiS_Pr->UseCustomMode) {
1809      infoflag = SiS_Pr->CInfoFlag;
1810      xres = SiS_Pr->CHDisplay;
1811   } else {
1812      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
1813      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
1814   }
1815
1816   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
1817
1818   temp = xres / 16;
1819   if(infoflag & InterlaceMode) temp <<= 1;
1820   temp *= colordepth;
1821   if(xres % 16) temp += (colordepth >> 1);
1822
1823   return temp;
1824}
1825
1826/*********************************************/
1827/*                   SEQ                     */
1828/*********************************************/
1829
1830static void
1831SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1832{
1833   unsigned char SRdata;
1834   int i;
1835
1836   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
1837
1838   /* or "display off"  */
1839   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
1840
1841   /* determine whether to force x8 dotclock */
1842   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
1843
1844      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1845         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
1846      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
1847
1848   }
1849
1850   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
1851
1852   for(i = 2; i <= 4; i++) {
1853      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
1854      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
1855   }
1856}
1857
1858/*********************************************/
1859/*                  MISC                     */
1860/*********************************************/
1861
1862static void
1863SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1864{
1865   unsigned char Miscdata;
1866
1867   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
1868
1869   if(SiS_Pr->ChipType < SIS_661) {
1870      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1871         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1872           Miscdata |= 0x0C;
1873         }
1874      }
1875   }
1876
1877   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
1878}
1879
1880/*********************************************/
1881/*                  CRTC                     */
1882/*********************************************/
1883
1884static void
1885SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1886{
1887   unsigned char  CRTCdata;
1888   unsigned short i;
1889
1890   /* Unlock CRTC */
1891   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
1892
1893   for(i = 0; i <= 0x18; i++) {
1894      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1895      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1896   }
1897
1898   if(SiS_Pr->ChipType >= SIS_661) {
1899      SiS_OpenCRTC(SiS_Pr);
1900      for(i = 0x13; i <= 0x14; i++) {
1901         CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1902         SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1903      }
1904   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
1905                (SiS_Pr->ChipType == SIS_730) )  &&
1906              (SiS_Pr->ChipRevision >= 0x30) ) {
1907      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1908         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1909            SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
1910         }
1911      }
1912   }
1913}
1914
1915/*********************************************/
1916/*                   ATT                     */
1917/*********************************************/
1918
1919static void
1920SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1921{
1922   unsigned char  ARdata;
1923   unsigned short i;
1924
1925   for(i = 0; i <= 0x13; i++) {
1926      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
1927
1928      if(i == 0x13) {
1929         /* Pixel shift. If screen on LCD or TV is shifted left or right,
1930          * this might be the cause.
1931          */
1932         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1933            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
1934         }
1935         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1936            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1937               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1938                  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1939               }
1940            }
1941         }
1942         if(SiS_Pr->ChipType >= SIS_661) {
1943            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
1944               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1945            }
1946         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
1947            if(SiS_Pr->ChipType >= SIS_315H) {
1948               if(IS_SIS550650740660) {
1949                  /* 315, 330 don't do this */
1950                  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1951                     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1952                  } else {
1953                     ARdata = 0;
1954                  }
1955               }
1956            } else {
1957               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1958            }
1959         }
1960      }
1961      SiS_GetRegByte(SiS_Pr->SiS_P3da);         /* reset 3da  */
1962      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);       /* set index  */
1963      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);  /* set data   */
1964   }
1965
1966   SiS_GetRegByte(SiS_Pr->SiS_P3da);            /* reset 3da  */
1967   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);       /* set index  */
1968   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);       /* set data   */
1969
1970   SiS_GetRegByte(SiS_Pr->SiS_P3da);
1971   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);       /* Enable Attribute  */
1972   SiS_GetRegByte(SiS_Pr->SiS_P3da);
1973}
1974
1975/*********************************************/
1976/*                   GRC                     */
1977/*********************************************/
1978
1979static void
1980SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1981{
1982   unsigned char  GRdata;
1983   unsigned short i;
1984
1985   for(i = 0; i <= 0x08; i++) {
1986      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
1987      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
1988   }
1989
1990   if(SiS_Pr->SiS_ModeType > ModeVGA) {
1991      /* 256 color disable */
1992      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
1993   }
1994}
1995
1996/*********************************************/
1997/*          CLEAR EXTENDED REGISTERS         */
1998/*********************************************/
1999
2000static void
2001SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
2002{
2003   unsigned short i;
2004
2005   for(i = 0x0A; i <= 0x0E; i++) {
2006      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
2007   }
2008
2009   if(SiS_Pr->ChipType >= SIS_315H) {
2010      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
2011      if(ModeNo <= 0x13) {
2012         if(ModeNo == 0x06 || ModeNo >= 0x0e) {
2013            SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
2014         }
2015      }
2016   }
2017}
2018
2019/*********************************************/
2020/*                 RESET VCLK                */
2021/*********************************************/
2022
2023static void
2024SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
2025{
2026   if(SiS_Pr->ChipType >= SIS_315H) {
2027      if(SiS_Pr->ChipType < SIS_661) {
2028         if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
2029      }
2030   } else {
2031      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
2032         (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
2033         return;
2034      }
2035   }
2036
2037   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
2038   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
2039   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
2040   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2041   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
2042   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
2043   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
2044   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2045}
2046
2047/*********************************************/
2048/*                  SYNC                     */
2049/*********************************************/
2050
2051static void
2052SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
2053{
2054   unsigned short sync;
2055
2056   if(SiS_Pr->UseCustomMode) {
2057      sync = SiS_Pr->CInfoFlag >> 8;
2058   } else {
2059      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
2060   }
2061
2062   sync &= 0xC0;
2063   sync |= 0x2f;
2064   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
2065}
2066
2067/*********************************************/
2068/*                  CRTC/2                   */
2069/*********************************************/
2070
2071static void
2072SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2073                unsigned short ModeIdIndex, unsigned short RRTI)
2074{
2075   unsigned short temp, i, j, modeflag;
2076   unsigned char  *crt1data = NULL;
2077
2078   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2079
2080   if(SiS_Pr->UseCustomMode) {
2081
2082      crt1data = &SiS_Pr->CCRT1CRTC[0];
2083
2084   } else {
2085
2086      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
2087
2088      /* Alternate for 1600x1200 LCDA */
2089      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
2090
2091      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
2092
2093   }
2094
2095   /* unlock cr0-7 */
2096   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
2097
2098   for(i = 0, j = 0; i <= 7; i++, j++) {
2099      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2100   }
2101   for(j = 0x10; i <= 10; i++, j++) {
2102      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2103   }
2104   for(j = 0x15; i <= 12; i++, j++) {
2105      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2106   }
2107   for(j = 0x0A; i <= 15; i++, j++) {
2108      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
2109   }
2110
2111   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
2112
2113   temp = (crt1data[16] & 0x01) << 5;
2114   if(modeflag & DoubleScanMode) temp |= 0x80;
2115   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
2116
2117   if(SiS_Pr->SiS_ModeType > ModeVGA) {
2118      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
2119   }
2120
2121#ifdef CONFIG_FB_SIS_315
2122   if(SiS_Pr->ChipType == XGI_20) {
2123      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
2124      if(!(temp = crt1data[5] & 0x1f)) {
2125         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
2126      }
2127      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
2128      temp = (crt1data[16] >> 5) + 3;
2129      if(temp > 7) temp -= 7;
2130      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
2131   }
2132#endif
2133}
2134
2135/*********************************************/
2136/*               OFFSET & PITCH              */
2137/*********************************************/
2138/*  (partly overruled by SetPitch() in XF86) */
2139/*********************************************/
2140
2141static void
2142SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2143                unsigned short ModeIdIndex, unsigned short RRTI)
2144{
2145   unsigned short temp, DisplayUnit, infoflag;
2146
2147   if(SiS_Pr->UseCustomMode) {
2148      infoflag = SiS_Pr->CInfoFlag;
2149   } else {
2150      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2151   }
2152
2153   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2154
2155   temp = (DisplayUnit >> 8) & 0x0f;
2156   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
2157
2158   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
2159
2160   if(infoflag & InterlaceMode) DisplayUnit >>= 1;
2161
2162   DisplayUnit <<= 5;
2163   temp = (DisplayUnit >> 8) + 1;
2164   if(DisplayUnit & 0xff) temp++;
2165   if(SiS_Pr->ChipType == XGI_20) {
2166      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
2167   }
2168   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
2169}
2170
2171/*********************************************/
2172/*                  VCLK                     */
2173/*********************************************/
2174
2175static void
2176SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2177                unsigned short ModeIdIndex, unsigned short RRTI)
2178{
2179   unsigned short index = 0, clka, clkb;
2180
2181   if(SiS_Pr->UseCustomMode) {
2182      clka = SiS_Pr->CSR2B;
2183      clkb = SiS_Pr->CSR2C;
2184   } else {
2185      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2186      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
2187         (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2188         /* Alternate for 1600x1200 LCDA */
2189         if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
2190         clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
2191         clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
2192      } else {
2193         clka = SiS_Pr->SiS_VCLKData[index].SR2B;
2194         clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
2195      }
2196   }
2197
2198   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
2199
2200   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
2201   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2202
2203   if(SiS_Pr->ChipType >= SIS_315H) {
2204#ifdef CONFIG_FB_SIS_315
2205      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
2206      if(SiS_Pr->ChipType == XGI_20) {
2207         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2208         if(mf & HalfDCLK) {
2209            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
2210            clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
2211            clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
2212            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2213         }
2214      }
2215#endif
2216   } else {
2217      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2218   }
2219}
2220
2221/*********************************************/
2222/*                  FIFO                     */
2223/*********************************************/
2224
2225#ifdef CONFIG_FB_SIS_300
2226void
2227SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
2228                unsigned short *idx2)
2229{
2230   unsigned short temp1, temp2;
2231   static const unsigned char ThTiming[8] = {
2232                1, 2, 2, 3, 0, 1, 1, 2
2233   };
2234
2235   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
2236   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
2237   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
2238   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
2239   (*idx1) <<= 1;
2240}
2241
2242static unsigned short
2243SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
2244{
2245   static const unsigned char ThLowA[8 * 3] = {
2246                61, 3,52, 5,68, 7,100,11,
2247                43, 3,42, 5,54, 7, 78,11,
2248                34, 3,37, 5,47, 7, 67,11
2249   };
2250
2251   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
2252}
2253
2254unsigned short
2255SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
2256{
2257   static const unsigned char ThLowB[8 * 3] = {
2258                81, 4,72, 6,88, 8,120,12,
2259                55, 4,54, 6,66, 8, 90,12,
2260                42, 4,45, 6,55, 8, 75,12
2261   };
2262
2263   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
2264}
2265
2266static unsigned short
2267SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
2268                unsigned short colordepth, unsigned short key)
2269{
2270   unsigned short idx1, idx2;
2271   unsigned int   longtemp = VCLK * colordepth;
2272
2273   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
2274
2275   if(key == 0) {
2276      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
2277   } else {
2278      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
2279   }
2280   idx1 = longtemp % (MCLK * 16);
2281   longtemp /= (MCLK * 16);
2282   if(idx1) longtemp++;
2283   return (unsigned short)longtemp;
2284}
2285
2286static unsigned short
2287SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
2288                unsigned short colordepth, unsigned short MCLK)
2289{
2290   unsigned short temp1, temp2;
2291
2292   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
2293   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
2294   if(temp1 < 4) temp1 = 4;
2295   temp1 -= 4;
2296   if(temp2 < temp1) temp2 = temp1;
2297   return temp2;
2298}
2299
2300static void
2301SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2302                unsigned short RefreshRateTableIndex)
2303{
2304   unsigned short ThresholdLow = 0;
2305   unsigned short temp, index, VCLK, MCLK, colorth;
2306   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
2307
2308   if(ModeNo > 0x13) {
2309
2310      /* Get VCLK  */
2311      if(SiS_Pr->UseCustomMode) {
2312         VCLK = SiS_Pr->CSRClock;
2313      } else {
2314         index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2315         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2316      }
2317
2318      /* Get half colordepth */
2319      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2320
2321      /* Get MCLK  */
2322      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
2323      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
2324
2325      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
2326      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
2327
2328      do {
2329         ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
2330         if(ThresholdLow < 0x13) break;
2331         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
2332         ThresholdLow = 0x13;
2333         temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
2334         if(!temp) break;
2335         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
2336      } while(0);
2337
2338   } else ThresholdLow = 2;
2339
2340   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2341   temp = (ThresholdLow << 4) | 0x0f;
2342   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
2343
2344   temp = (ThresholdLow & 0x10) << 1;
2345   if(ModeNo > 0x13) temp |= 0x40;
2346   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
2347
2348   /* What is this? */
2349   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2350
2351   /* Write CRT/CPU threshold high */
2352   temp = ThresholdLow + 3;
2353   if(temp > 0x0f) temp = 0x0f;
2354   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
2355}
2356
2357unsigned short
2358SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
2359{
2360   static const unsigned char LatencyFactor[] = {
2361                97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
2362                 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
2363                97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
2364                 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
2365                80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
2366                 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
2367                86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
2368                 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
2369   };
2370   static const unsigned char LatencyFactor730[] = {
2371                 69, 63, 61,
2372                 86, 79, 77,
2373                103, 96, 94,
2374                120,113,111,
2375                137,130,128
2376   };
2377
2378   if(SiS_Pr->ChipType == SIS_730) {
2379      return (unsigned short)LatencyFactor730[index];
2380   } else {
2381      return (unsigned short)LatencyFactor[index];
2382   }
2383}
2384
2385static unsigned short
2386SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
2387{
2388   unsigned short index;
2389
2390   if(SiS_Pr->ChipType == SIS_730) {
2391      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
2392   } else {
2393      index = (key & 0xe0) >> 5;
2394      if(key & 0x10)    index +=  6;
2395      if(!(key & 0x01)) index += 24;
2396      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
2397   }
2398   return SiS_GetLatencyFactor630(SiS_Pr, index);
2399}
2400
2401static void
2402SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2403                    unsigned short RefreshRateTableIndex)
2404{
2405   unsigned short  ThresholdLow = 0;
2406   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
2407   unsigned int    templ, datal;
2408   const unsigned char *queuedata = NULL;
2409   static const unsigned char FQBQData[21] = {
2410                0x01,0x21,0x41,0x61,0x81,
2411                0x31,0x51,0x71,0x91,0xb1,
2412                0x00,0x20,0x40,0x60,0x80,
2413                0x30,0x50,0x70,0x90,0xb0,
2414                0xff
2415   };
2416   static const unsigned char FQBQData730[16] = {
2417                0x34,0x74,0xb4,
2418                0x23,0x63,0xa3,
2419                0x12,0x52,0x92,
2420                0x01,0x41,0x81,
2421                0x00,0x40,0x80,
2422                0xff
2423   };
2424   static const unsigned short colortharray[6] = {
2425                1, 1, 2, 2, 3, 4
2426   };
2427
2428   i = 0;
2429
2430   if(ModeNo > 0x13) {
2431
2432      /* Get VCLK  */
2433      if(SiS_Pr->UseCustomMode) {
2434         VCLK = SiS_Pr->CSRClock;
2435      } else {
2436         data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2437         VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
2438      }
2439
2440      /* Get MCLK * 16 */
2441      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
2442      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
2443
2444      /* Get half colordepth */
2445      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2446
2447      if(SiS_Pr->ChipType == SIS_730) {
2448         queuedata = &FQBQData730[0];
2449      } else {
2450         queuedata = &FQBQData[0];
2451      }
2452
2453      do {
2454         templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
2455
2456         datal = templ % MCLK16;
2457         templ = (templ / MCLK16) + 1;
2458         if(datal) templ++;
2459
2460         if(templ > 0x13) {
2461            if(queuedata[i + 1] == 0xFF) {
2462               ThresholdLow = 0x13;
2463               break;
2464            }
2465            i++;
2466         } else {
2467            ThresholdLow = templ;
2468            break;
2469         }
2470      } while(queuedata[i] != 0xFF);
2471
2472   } else {
2473
2474      if(SiS_Pr->ChipType != SIS_730) i = 9;
2475      ThresholdLow = 0x02;
2476
2477   }
2478
2479   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2480   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
2481   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
2482
2483   data = (ThresholdLow & 0x10) << 1;
2484   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
2485
2486   /* What is this? */
2487   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2488
2489   /* Write CRT/CPU threshold high (gap = 3) */
2490   data = ThresholdLow + 3;
2491   if(data > 0x0f) data = 0x0f;
2492   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
2493
2494  /* Write foreground and background queue */
2495   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
2496
2497   if(SiS_Pr->ChipType == SIS_730) {
2498
2499      templ &= 0xfffff9ff;
2500      templ |= ((queuedata[i] & 0xc0) << 3);
2501
2502   } else {
2503
2504      templ &= 0xf0ffffff;
2505      if( (ModeNo <= 0x13) &&
2506          (SiS_Pr->ChipType == SIS_630) &&
2507          (SiS_Pr->ChipRevision >= 0x30) ) {
2508         templ |= 0x0b000000;
2509      } else {
2510         templ |= ((queuedata[i] & 0xf0) << 20);
2511      }
2512
2513   }
2514
2515   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
2516   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
2517
2518   /* GUI grant timer (PCI config 0xA3) */
2519   if(SiS_Pr->ChipType == SIS_730) {
2520
2521      templ &= 0x00ffffff;
2522      datal = queuedata[i] << 8;
2523      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
2524
2525   } else {
2526
2527      templ &= 0xf0ffffff;
2528      templ |= ((queuedata[i] & 0x0f) << 24);
2529
2530   }
2531
2532   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
2533}
2534#endif /* CONFIG_FB_SIS_300 */
2535
2536#ifdef CONFIG_FB_SIS_315
2537static void
2538SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2539{
2540   unsigned short modeflag;
2541
2542   /* disable auto-threshold */
2543   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
2544
2545   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2546
2547   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
2548   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
2549   if(ModeNo > 0x13) {
2550      if(SiS_Pr->ChipType >= XGI_20) {
2551         SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2552         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2553      } else if(SiS_Pr->ChipType >= SIS_661) {
2554         if(!(modeflag & HalfDCLK)) {
2555            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2556            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2557         }
2558      } else {
2559         if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
2560            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2561            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2562         }
2563      }
2564   }
2565}
2566#endif
2567
2568/*********************************************/
2569/*              MODE REGISTERS               */
2570/*********************************************/
2571
2572static void
2573SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2574                unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
2575{
2576   unsigned short data = 0, VCLK = 0, index = 0;
2577
2578   if(ModeNo > 0x13) {
2579      if(SiS_Pr->UseCustomMode) {
2580         VCLK = SiS_Pr->CSRClock;
2581      } else {
2582         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2583         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2584      }
2585   }
2586
2587   if(SiS_Pr->ChipType < SIS_315H) {
2588#ifdef CONFIG_FB_SIS_300
2589      if(VCLK > 150) data |= 0x80;
2590      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
2591
2592      data = 0x00;
2593      if(VCLK >= 150) data |= 0x08;
2594      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
2595#endif
2596   } else if(SiS_Pr->ChipType < XGI_20) {
2597#ifdef CONFIG_FB_SIS_315
2598      if(VCLK >= 166) data |= 0x0c;
2599      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2600
2601      if(VCLK >= 166) {
2602         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
2603      }
2604#endif
2605   } else {
2606#ifdef CONFIG_FB_SIS_315
2607      if(VCLK >= 200) data |= 0x0c;
2608      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
2609      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2610      if(SiS_Pr->ChipType != XGI_20) {
2611         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
2612         if(VCLK < 200) data |= 0x10;
2613         SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
2614      }
2615#endif
2616   }
2617
2618   /* DAC speed */
2619   if(SiS_Pr->ChipType >= SIS_661) {
2620
2621      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
2622
2623   } else {
2624
2625      data = 0x03;
2626      if(VCLK >= 260)      data = 0x00;
2627      else if(VCLK >= 160) data = 0x01;
2628      else if(VCLK >= 135) data = 0x02;
2629
2630      if(SiS_Pr->ChipType == SIS_540) {
2631         /* Was == 203 or < 234 which made no sense */
2632         if (VCLK < 234) data = 0x02;
2633      }
2634
2635      if(SiS_Pr->ChipType < SIS_315H) {
2636         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
2637      } else {
2638         if(SiS_Pr->ChipType > SIS_315PRO) {
2639            if(ModeNo > 0x13) data &= 0xfc;
2640         }
2641         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
2642      }
2643
2644   }
2645}
2646
2647static void
2648SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2649                unsigned short ModeIdIndex, unsigned short RRTI)
2650{
2651   unsigned short data, infoflag = 0, modeflag, resindex;
2652#ifdef CONFIG_FB_SIS_315
2653   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
2654   unsigned short data2, data3;
2655#endif
2656
2657   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2658
2659   if(SiS_Pr->UseCustomMode) {
2660      infoflag = SiS_Pr->CInfoFlag;
2661   } else {
2662      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
2663      if(ModeNo > 0x13) {
2664         infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2665      }
2666   }
2667
2668   /* Disable DPMS */
2669   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
2670
2671   data = 0;
2672   if(ModeNo > 0x13) {
2673      if(SiS_Pr->SiS_ModeType > ModeEGA) {
2674         data |= 0x02;
2675         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
2676      }
2677      if(infoflag & InterlaceMode) data |= 0x20;
2678   }
2679   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
2680
2681   if(SiS_Pr->ChipType != SIS_300) {
2682      data = 0;
2683      if(infoflag & InterlaceMode) {
2684         /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
2685         int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
2686                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
2687         int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
2688                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
2689         data = hrs - (hto >> 1) + 3;
2690      }
2691      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
2692      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
2693   }
2694
2695   if(modeflag & HalfDCLK) {
2696      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
2697   }
2698
2699   data = 0;
2700   if(modeflag & LineCompareOff) data = 0x08;
2701   if(SiS_Pr->ChipType == SIS_300) {
2702      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
2703   } else {
2704      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
2705      if(SiS_Pr->SiS_ModeType == ModeEGA) {
2706         if(ModeNo > 0x13) {
2707            data |= 0x40;
2708         }
2709      }
2710      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
2711   }
2712
2713#ifdef CONFIG_FB_SIS_315
2714   if(SiS_Pr->ChipType >= SIS_315H) {
2715      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
2716   }
2717
2718   if(SiS_Pr->ChipType == SIS_315PRO) {
2719
2720      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
2721      if(SiS_Pr->SiS_ModeType == ModeText) {
2722         data &= 0xc7;
2723      } else {
2724         data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
2725         if(infoflag & InterlaceMode) data2 >>= 1;
2726         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2727         if(data3) data2 /= data3;
2728         if(data2 >= 0x50) {
2729            data &= 0x0f;
2730            data |= 0x50;
2731         }
2732      }
2733      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2734
2735   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
2736
2737      data = SiS_Get310DRAMType(SiS_Pr);
2738      if(SiS_Pr->ChipType == SIS_330) {
2739         data = SiS_Pr->SiS_SR15[(2 * 4) + data];
2740      } else {
2741         if(SiS_Pr->SiS_ROMNew)      data = ROMAddr[0xf6];
2742         else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
2743         else                        data = 0xba;
2744      }
2745      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
2746         data &= 0xc7;
2747      } else {
2748         if(SiS_Pr->UseCustomMode) {
2749            data2 = SiS_Pr->CSRClock;
2750         } else {
2751            data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2752            data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
2753         }
2754
2755         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2756         if(data3) data2 *= data3;
2757
2758         data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
2759
2760         if(SiS_Pr->ChipType == SIS_330) {
2761            if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
2762               if     (data2 >= 0x19c) data = 0xba;
2763               else if(data2 >= 0x140) data = 0x7a;
2764               else if(data2 >= 0x101) data = 0x3a;
2765               else if(data2 >= 0xf5)  data = 0x32;
2766               else if(data2 >= 0xe2)  data = 0x2a;
2767               else if(data2 >= 0xc4)  data = 0x22;
2768               else if(data2 >= 0xac)  data = 0x1a;
2769               else if(data2 >= 0x9e)  data = 0x12;
2770               else if(data2 >= 0x8e)  data = 0x0a;
2771               else                    data = 0x02;
2772            } else {
2773               if(data2 >= 0x127)      data = 0xba;
2774               else                    data = 0x7a;
2775            }
2776         } else {  /* 76x+LFB */
2777            if     (data2 >= 0x190) data = 0xba;
2778            else if(data2 >= 0xff)  data = 0x7a;
2779            else if(data2 >= 0xd3)  data = 0x3a;
2780            else if(data2 >= 0xa9)  data = 0x1a;
2781            else if(data2 >= 0x93)  data = 0x0a;
2782            else                    data = 0x02;
2783         }
2784      }
2785      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2786
2787   }
2788      /* XGI: Nothing. */
2789      /* TODO: Check SiS340 */
2790#endif
2791
2792   data = 0x60;
2793   if(SiS_Pr->SiS_ModeType != ModeText) {
2794      data ^= 0x60;
2795      if(SiS_Pr->SiS_ModeType != ModeEGA) {
2796         data ^= 0xA0;
2797      }
2798   }
2799   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
2800
2801   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
2802
2803#ifdef CONFIG_FB_SIS_315
2804   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
2805       (SiS_Pr->ChipType == XGI_40)) {
2806      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2807         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
2808      } else {
2809         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
2810      }
2811   } else if(SiS_Pr->ChipType == XGI_20) {
2812      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2813         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
2814      } else {
2815         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
2816      }
2817      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
2818   }
2819#endif
2820}
2821
2822#ifdef CONFIG_FB_SIS_315
2823static void
2824SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
2825{
2826#if 0
2827   /* TODO: Find out about IOAddress2 */
2828   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
2829   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
2830   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
2831   int i;
2832
2833   if((SiS_Pr->ChipRevision != 0) ||
2834      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
2835      return;
2836
2837   for(i = 0; i <= 4; i++) {                                    /* SR00 - SR04 */
2838      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
2839   }
2840   for(i = 0; i <= 8; i++) {                                    /* GR00 - GR08 */
2841      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
2842   }
2843   SiS_SetReg(P2_3c4,0x05,0x86);
2844   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));   /* SR06 */
2845   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));   /* SR21 */
2846   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));     /* MISC */
2847   SiS_SetReg(P2_3c4,0x05,0x00);
2848#endif
2849}
2850#endif
2851
2852/*********************************************/
2853/*                 LOAD DAC                  */
2854/*********************************************/
2855
2856static void
2857SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
2858             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
2859{
2860   unsigned short d1, d2, d3;
2861
2862   switch(dl) {
2863   case  0: d1 = dh; d2 = ah; d3 = al; break;
2864   case  1: d1 = ah; d2 = al; d3 = dh; break;
2865   default: d1 = al; d2 = dh; d3 = ah;
2866   }
2867   SiS_SetRegByte(DACData, (d1 << shiftflag));
2868   SiS_SetRegByte(DACData, (d2 << shiftflag));
2869   SiS_SetRegByte(DACData, (d3 << shiftflag));
2870}
2871
2872void
2873SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2874{
2875   unsigned short data, data2, time, i, j, k, m, n, o;
2876   unsigned short si, di, bx, sf;
2877   SISIOADDRESS DACAddr, DACData;
2878   const unsigned char *table = NULL;
2879
2880   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
2881
2882   j = time = 64;
2883   if(data == 0x00)      table = SiS_MDA_DAC;
2884   else if(data == 0x08) table = SiS_CGA_DAC;
2885   else if(data == 0x10) table = SiS_EGA_DAC;
2886   else if(data == 0x18) {
2887      j = 16;
2888      time = 256;
2889      table = SiS_VGA_DAC;
2890   }
2891
2892   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
2893         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
2894       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
2895       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
2896      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
2897      DACAddr = SiS_Pr->SiS_P3c8;
2898      DACData = SiS_Pr->SiS_P3c9;
2899      sf = 0;
2900   } else {
2901      DACAddr = SiS_Pr->SiS_Part5Port;
2902      DACData = SiS_Pr->SiS_Part5Port + 1;
2903      sf = 2;
2904   }
2905
2906   SiS_SetRegByte(DACAddr,0x00);
2907
2908   for(i = 0; i < j; i++) {
2909      data = table[i];
2910      for(k = 0; k < 3; k++) {
2911        data2 = 0;
2912        if(data & 0x01) data2 += 0x2A;
2913        if(data & 0x02) data2 += 0x15;
2914        SiS_SetRegByte(DACData, (data2 << sf));
2915        data >>= 2;
2916      }
2917   }
2918
2919   if(time == 256) {
2920      for(i = 16; i < 32; i++) {
2921         data = table[i] << sf;
2922         for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
2923      }
2924      si = 32;
2925      for(m = 0; m < 9; m++) {
2926         di = si;
2927         bx = si + 4;
2928         for(n = 0; n < 3; n++) {
2929            for(o = 0; o < 5; o++) {
2930               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
2931               si++;
2932            }
2933            si -= 2;
2934            for(o = 0; o < 3; o++) {
2935               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
2936               si--;
2937            }
2938         }            /* for n < 3 */
2939         si += 5;
2940      }               /* for m < 9 */
2941   }
2942}
2943
2944/*********************************************/
2945/*         SET CRT1 REGISTER GROUP           */
2946/*********************************************/
2947
2948static void
2949SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2950{
2951   unsigned short StandTableIndex, RefreshRateTableIndex;
2952
2953   SiS_Pr->SiS_CRT1Mode = ModeNo;
2954
2955   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
2956
2957   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
2958      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
2959         SiS_DisableBridge(SiS_Pr);
2960      }
2961   }
2962
2963   SiS_ResetSegmentRegisters(SiS_Pr);
2964
2965   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
2966   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
2967   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
2968   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
2969   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
2970   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
2971   SiS_ResetCRT1VCLK(SiS_Pr);
2972
2973   SiS_Pr->SiS_SelectCRT2Rate = 0;
2974   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
2975
2976   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
2977      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2978         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2979      }
2980   }
2981
2982   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2983      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2984   }
2985
2986   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
2987
2988   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2989      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
2990   }
2991
2992   if(RefreshRateTableIndex != 0xFFFF) {
2993      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
2994      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2995      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2996      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2997   }
2998
2999   switch(SiS_Pr->ChipType) {
3000#ifdef CONFIG_FB_SIS_300
3001   case SIS_300:
3002      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
3003      break;
3004   case SIS_540:
3005   case SIS_630:
3006   case SIS_730:
3007      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
3008      break;
3009#endif
3010   default:
3011#ifdef CONFIG_FB_SIS_315
3012      if(SiS_Pr->ChipType == XGI_20) {
3013         unsigned char sr2b = 0, sr2c = 0;
3014         switch(ModeNo) {
3015         case 0x00:
3016         case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
3017         case 0x04:
3018         case 0x05:
3019         case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
3020         }
3021         if(sr2b) {
3022            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
3023            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
3024            SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
3025         }
3026      }
3027      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
3028#endif
3029      break;
3030   }
3031
3032   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3033
3034#ifdef CONFIG_FB_SIS_315
3035   if(SiS_Pr->ChipType == XGI_40) {
3036      SiS_SetupDualChip(SiS_Pr);
3037   }
3038#endif
3039
3040   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
3041
3042   if(SiS_Pr->SiS_flag_clearbuffer) {
3043      SiS_ClearBuffer(SiS_Pr, ModeNo);
3044   }
3045
3046   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
3047      SiS_WaitRetrace1(SiS_Pr);
3048      SiS_DisplayOn(SiS_Pr);
3049   }
3050}
3051
3052/*********************************************/
3053/*       HELPER: VIDEO BRIDGE PROG CLK       */
3054/*********************************************/
3055
3056static void
3057SiS_InitVB(struct SiS_Private *SiS_Pr)
3058{
3059   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3060
3061   SiS_Pr->Init_P4_0E = 0;
3062   if(SiS_Pr->SiS_ROMNew) {
3063      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
3064   } else if(SiS_Pr->ChipType >= XGI_40) {
3065      if(SiS_Pr->SiS_XGIROM) {
3066         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
3067      }
3068   }
3069}
3070
3071static void
3072SiS_ResetVB(struct SiS_Private *SiS_Pr)
3073{
3074#ifdef CONFIG_FB_SIS_315
3075   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
3076   unsigned short temp;
3077
3078   /* VB programming clock */
3079   if(SiS_Pr->SiS_UseROM) {
3080      if(SiS_Pr->ChipType < SIS_330) {
3081         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
3082         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3083         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3084      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
3085         temp = ROMAddr[0x7e] | 0x40;
3086         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3087         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3088      }
3089   } else if(SiS_Pr->ChipType >= XGI_40) {
3090      temp = 0x40;
3091      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
3092      /* Can we do this on any chipset? */
3093      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3094   }
3095#endif
3096}
3097
3098/*********************************************/
3099/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
3100/*********************************************/
3101
3102static void
3103SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3104{
3105   /* SiS65x and XGI set up some sort of "lock mode" for text
3106    * which locks CRT2 in some way to CRT1 timing. Disable
3107    * this here.
3108    */
3109#ifdef CONFIG_FB_SIS_315
3110   if((IS_SIS651) || (IS_SISM650) ||
3111      SiS_Pr->ChipType == SIS_340 ||
3112      SiS_Pr->ChipType == XGI_40) {
3113      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
3114      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
3115      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
3116      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
3117      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
3118   }
3119   /* !!! This does not support modes < 0x13 !!! */
3120#endif
3121}
3122
3123/*********************************************/
3124/*     HELPER: SET AGP TIMING FOR SiS760     */
3125/*********************************************/
3126
3127static void
3128SiS_Handle760(struct SiS_Private *SiS_Pr)
3129{
3130#ifdef CONFIG_FB_SIS_315
3131   unsigned int somebase;
3132   unsigned char temp1, temp2, temp3;
3133
3134   if( (SiS_Pr->ChipType != SIS_760)                         ||
3135       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
3136       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
3137       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
3138      return;
3139
3140   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
3141   somebase &= 0xffff;
3142
3143   if(somebase == 0) return;
3144
3145   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
3146
3147   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
3148      temp1 = 0x21;
3149      temp2 = 0x03;
3150      temp3 |= 0x08;
3151   } else {
3152      temp1 = 0x25;
3153      temp2 = 0x0b;
3154   }
3155
3156   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
3157   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
3158
3159   SiS_SetRegByte((somebase + 0x85), temp3);
3160#endif
3161}
3162
3163/*********************************************/
3164/*                 SiSSetMode()              */
3165/*********************************************/
3166
3167bool
3168SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3169{
3170   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3171   unsigned short RealModeNo, ModeIdIndex;
3172   unsigned char  backupreg = 0;
3173   unsigned short KeepLockReg;
3174
3175   SiS_Pr->UseCustomMode = false;
3176   SiS_Pr->CRT1UsesCustomMode = false;
3177
3178   SiS_Pr->SiS_flag_clearbuffer = 0;
3179
3180   if(SiS_Pr->UseCustomMode) {
3181      ModeNo = 0xfe;
3182   } else {
3183      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
3184      ModeNo &= 0x7f;
3185   }
3186
3187   /* Don't use FSTN mode for CRT1 */
3188   RealModeNo = ModeNo;
3189   if(ModeNo == 0x5b) ModeNo = 0x56;
3190
3191   SiSInitPtr(SiS_Pr);
3192   SiSRegInit(SiS_Pr, BaseAddr);
3193   SiS_GetSysFlags(SiS_Pr);
3194
3195   SiS_Pr->SiS_VGAINFO = 0x11;
3196
3197   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
3198   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3199
3200   SiSInitPCIetc(SiS_Pr);
3201   SiSSetLVDSetc(SiS_Pr);
3202   SiSDetermineROMUsage(SiS_Pr);
3203
3204   SiS_UnLockCRT2(SiS_Pr);
3205
3206   if(!SiS_Pr->UseCustomMode) {
3207      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3208   } else {
3209      ModeIdIndex = 0;
3210   }
3211
3212   SiS_GetVBType(SiS_Pr);
3213
3214   /* Init/restore some VB registers */
3215   SiS_InitVB(SiS_Pr);
3216   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3217      if(SiS_Pr->ChipType >= SIS_315H) {
3218         SiS_ResetVB(SiS_Pr);
3219         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3220         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3221         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3222      } else {
3223         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3224      }
3225   }
3226
3227   /* Get VB information (connectors, connected devices) */
3228   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
3229   SiS_SetYPbPr(SiS_Pr);
3230   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3231   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3232   SiS_SetLowModeTest(SiS_Pr, ModeNo);
3233
3234   /* Check memory size (kernel framebuffer driver only) */
3235   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
3236      return false;
3237   }
3238
3239   SiS_OpenCRTC(SiS_Pr);
3240
3241   if(SiS_Pr->UseCustomMode) {
3242      SiS_Pr->CRT1UsesCustomMode = true;
3243      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3244      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3245   } else {
3246      SiS_Pr->CRT1UsesCustomMode = false;
3247   }
3248
3249   /* Set mode on CRT1 */
3250   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
3251       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
3252      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3253   }
3254
3255   /* Set mode on CRT2 */
3256   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
3257      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
3258          (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
3259          (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
3260          (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3261         SiS_SetCRT2Group(SiS_Pr, RealModeNo);
3262      }
3263   }
3264
3265   SiS_HandleCRT1(SiS_Pr);
3266
3267   SiS_StrangeStuff(SiS_Pr);
3268
3269   SiS_DisplayOn(SiS_Pr);
3270   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3271
3272#ifdef CONFIG_FB_SIS_315
3273   if(SiS_Pr->ChipType >= SIS_315H) {
3274      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3275         if(!(SiS_IsDualEdge(SiS_Pr))) {
3276            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3277         }
3278      }
3279   }
3280#endif
3281
3282   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3283      if(SiS_Pr->ChipType >= SIS_315H) {
3284#ifdef CONFIG_FB_SIS_315
3285         if(!SiS_Pr->SiS_ROMNew) {
3286            if(SiS_IsVAMode(SiS_Pr)) {
3287               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3288            } else {
3289               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3290            }
3291         }
3292
3293         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3294
3295         if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
3296            if((ModeNo == 0x03) || (ModeNo == 0x10)) {
3297               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
3298               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
3299            }
3300         }
3301
3302         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3303            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3304         }
3305#endif
3306      } else if((SiS_Pr->ChipType == SIS_630) ||
3307                (SiS_Pr->ChipType == SIS_730)) {
3308         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3309      }
3310   }
3311
3312   SiS_CloseCRTC(SiS_Pr);
3313
3314   SiS_Handle760(SiS_Pr);
3315
3316   /* We never lock registers in XF86 */
3317   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
3318
3319   return true;
3320}
3321
3322#ifndef GETBITSTR
3323#define BITMASK(h,l)            (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
3324#define GENMASK(mask)           BITMASK(1?mask,0?mask)
3325#define GETBITS(var,mask)       (((var) & GENMASK(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