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#ifdef HAVE_CONFIG_H
  60#include "config.h"
  61#endif
  62
  63#include "init.h"
  64
  65#ifdef SIS300
  66#include "300vtbl.h"
  67#endif
  68
  69#ifdef SIS315H
  70#include "310vtbl.h"
  71#endif
  72
  73#if defined(ALLOC_PRAGMA)
  74#pragma alloc_text(PAGE,SiSSetMode)
  75#endif
  76
  77/*********************************************/
  78/*         POINTER INITIALIZATION            */
  79/*********************************************/
  80
  81#if defined(SIS300) || defined(SIS315H)
  82static void
  83InitCommonPointer(struct SiS_Private *SiS_Pr)
  84{
  85   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
  86   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
  87   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
  88   SiS_Pr->SiS_StandTable    = SiS_StandTable;
  89
  90   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
  91   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
  92   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
  93   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
  94
  95   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
  96   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
  97   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
  98#if 0
  99   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
 100   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
 101#endif
 102
 103   SiS_Pr->SiS_StPALData   = SiS_StPALData;
 104   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
 105   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
 106   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
 107   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
 108   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
 109   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
 110   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
 111   SiS_Pr->SiS_St525pData  = SiS_St525pData;
 112   SiS_Pr->SiS_St750pData  = SiS_St750pData;
 113   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
 114   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
 115   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;
 116
 117   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
 118   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
 119
 120   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
 121   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
 122   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
 123   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
 124   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
 125   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
 126   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
 127   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
 128   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
 129   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
 130   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
 131   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
 132   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
 133
 134   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
 135   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
 136   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
 137   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
 138   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
 139   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
 140
 141   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
 142   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
 143   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
 144   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
 145   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
 146   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
 147   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
 148#if 0
 149   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
 150   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
 151   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
 152   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
 153#endif
 154
 155   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
 156   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
 157
 158   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
 159   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
 160}
 161#endif
 162
 163#ifdef SIS300
 164static void
 165InitTo300Pointer(struct SiS_Private *SiS_Pr)
 166{
 167   InitCommonPointer(SiS_Pr);
 168
 169   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
 170   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
 171   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
 172   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
 173   if(SiS_Pr->ChipType == SIS_300) {
 174      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
 175   } else {
 176      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
 177   }
 178   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
 179   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;
 180
 181   SiS_Pr->SiS_SR15  = SiS300_SR15;
 182
 183   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
 184   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
 185
 186   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
 187   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
 188   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
 189   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
 190
 191   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
 192   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
 193   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
 194
 195   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
 196   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
 197   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
 198   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
 199   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
 200   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
 201   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
 202
 203   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
 204   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
 205   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
 206   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
 207   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
 208
 209   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
 210   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
 211   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
 212   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
 213
 214   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
 215   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
 216   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
 217   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
 218   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
 219   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
 220   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
 221   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
 222   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
 223   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
 224   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
 225   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
 226   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
 227   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
 228   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
 229   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
 230   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
 231   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;
 232   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */
 233   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */
 234   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
 235   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
 236   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
 237}
 238#endif
 239
 240#ifdef SIS315H
 241static void
 242InitTo310Pointer(struct SiS_Private *SiS_Pr)
 243{
 244   InitCommonPointer(SiS_Pr);
 245
 246   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
 247   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
 248   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
 249   if(SiS_Pr->ChipType >= SIS_340) {
 250      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
 251   } else if(SiS_Pr->ChipType >= SIS_761) {
 252      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
 253   } else if(SiS_Pr->ChipType >= SIS_760) {
 254      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
 255   } else if(SiS_Pr->ChipType >= SIS_661) {
 256      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
 257   } else if(SiS_Pr->ChipType == SIS_330) {
 258      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
 259   } else if(SiS_Pr->ChipType > SIS_315PRO) {
 260      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
 261   } else {
 262      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
 263   }
 264   if(SiS_Pr->ChipType >= SIS_340) {
 265      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
 266   } else {
 267      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
 268   }
 269   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
 270   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
 271
 272   SiS_Pr->SiS_SR15  = SiS310_SR15;
 273
 274   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
 275   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
 276
 277   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
 278   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
 279   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
 280   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
 281
 282   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
 283
 284   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
 285   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
 286   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
 287   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
 288   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
 289   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
 290   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
 291
 292   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
 293   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
 294   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
 295   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
 296   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
 297
 298   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
 299   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
 300   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
 301   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
 302   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
 303   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
 304   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
 305   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
 306   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
 307
 308   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
 309   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
 310   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
 311   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;
 312   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
 313   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
 314   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
 315   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
 316   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
 317}
 318#endif
 319
 320bool
 321SiSInitPtr(struct SiS_Private *SiS_Pr)
 322{
 323   if(SiS_Pr->ChipType < SIS_315H) {
 324#ifdef SIS300
 325      InitTo300Pointer(SiS_Pr);
 326#else
 327      return false;
 328#endif
 329   } else {
 330#ifdef SIS315H
 331      InitTo310Pointer(SiS_Pr);
 332#else
 333      return false;
 334#endif
 335   }
 336   return true;
 337}
 338
 339/*********************************************/
 340/*            HELPER: Get ModeID             */
 341/*********************************************/
 342
 343#ifndef SIS_XORG_XF86
 344static
 345#endif
 346unsigned short
 347SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
 348                int Depth, bool FSTN, int LCDwidth, int LCDheight)
 349{
 350   unsigned short ModeIndex = 0;
 351
 352   switch(HDisplay)
 353   {
 354        case 320:
 355                if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
 356                else if(VDisplay == 240) {
 357                        if((VBFlags & CRT2_LCD) && (FSTN))
 358                                ModeIndex = ModeIndex_320x240_FSTN[Depth];
 359                        else
 360                                ModeIndex = ModeIndex_320x240[Depth];
 361                }
 362                break;
 363        case 400:
 364                if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
 365                        if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 366                }
 367                break;
 368        case 512:
 369                if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
 370                        if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 371                }
 372                break;
 373        case 640:
 374                if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 375                else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 376                break;
 377        case 720:
 378                if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
 379                else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
 380                break;
 381        case 768:
 382                if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 383                break;
 384        case 800:
 385                if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
 386                else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
 387                break;
 388        case 848:
 389                if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 390                break;
 391        case 856:
 392                if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 393                break;
 394        case 960:
 395                if(VGAEngine == SIS_315_VGA) {
 396                        if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
 397                        else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
 398                }
 399                break;
 400        case 1024:
 401                if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
 402                else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
 403                else if(VGAEngine == SIS_300_VGA) {
 404                        if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
 405                }
 406                break;
 407        case 1152:
 408                if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
 409                if(VGAEngine == SIS_300_VGA) {
 410                        if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
 411                }
 412                break;
 413        case 1280:
 414                switch(VDisplay) {
 415                        case 720:
 416                                ModeIndex = ModeIndex_1280x720[Depth];
 417                                break;
 418                        case 768:
 419                                if(VGAEngine == SIS_300_VGA) {
 420                                        ModeIndex = ModeIndex_300_1280x768[Depth];
 421                                } else {
 422                                        ModeIndex = ModeIndex_310_1280x768[Depth];
 423                                }
 424                                break;
 425                        case 800:
 426                                if(VGAEngine == SIS_315_VGA) {
 427                                        ModeIndex = ModeIndex_1280x800[Depth];
 428                                }
 429                                break;
 430                        case 854:
 431                                if(VGAEngine == SIS_315_VGA) {
 432                                        ModeIndex = ModeIndex_1280x854[Depth];
 433                                }
 434                                break;
 435                        case 960:
 436                                ModeIndex = ModeIndex_1280x960[Depth];
 437                                break;
 438                        case 1024:
 439                                ModeIndex = ModeIndex_1280x1024[Depth];
 440                                break;
 441                }
 442                break;
 443        case 1360:
 444                if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
 445                if(VGAEngine == SIS_300_VGA) {
 446                        if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
 447                }
 448                break;
 449        case 1400:
 450                if(VGAEngine == SIS_315_VGA) {
 451                        if(VDisplay == 1050) {
 452                                ModeIndex = ModeIndex_1400x1050[Depth];
 453                        }
 454                }
 455                break;
 456        case 1600:
 457                if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
 458                break;
 459        case 1680:
 460                if(VGAEngine == SIS_315_VGA) {
 461                        if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
 462                }
 463                break;
 464        case 1920:
 465                if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
 466                else if(VGAEngine == SIS_315_VGA) {
 467                        if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
 468                }
 469                break;
 470        case 2048:
 471                if(VDisplay == 1536) {
 472                        if(VGAEngine == SIS_300_VGA) {
 473                                ModeIndex = ModeIndex_300_2048x1536[Depth];
 474                        } else {
 475                                ModeIndex = ModeIndex_310_2048x1536[Depth];
 476                        }
 477                }
 478                break;
 479   }
 480
 481   return ModeIndex;
 482}
 483
 484unsigned short
 485SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
 486                int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
 487                unsigned int VBFlags2)
 488{
 489   unsigned short ModeIndex = 0;
 490
 491   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
 492
 493      switch(HDisplay)
 494      {
 495        case 320:
 496             if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
 497                if(VDisplay == 200) {
 498                   if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
 499                } else if(VDisplay == 240) {
 500                   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
 501                   else if(VGAEngine == SIS_315_VGA) {
 502                      ModeIndex = ModeIndex_320x240_FSTN[Depth];
 503                   }
 504                }
 505             }
 506             break;
 507        case 400:
 508             if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
 509                if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
 510                   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 511                }
 512             }
 513             break;
 514        case 512:
 515             if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
 516                if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
 517                   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
 518                      if(VDisplay == 384) {
 519                         ModeIndex = ModeIndex_512x384[Depth];
 520                      }
 521                   }
 522                }
 523             }
 524             break;
 525        case 640:
 526             if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
 527             else if(VDisplay == 400) {
 528                if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
 529                   ModeIndex = ModeIndex_640x400[Depth];
 530             }
 531             break;
 532        case 800:
 533             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 534             break;
 535        case 848:
 536             if(CustomT == CUT_PANEL848) {
 537                if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 538             }
 539             break;
 540        case 856:
 541             if(CustomT == CUT_PANEL856) {
 542                if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 543             }
 544             break;
 545        case 1024:
 546             if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
 547             else if(VGAEngine == SIS_300_VGA) {
 548                if((VDisplay == 600) && (LCDheight == 600)) {
 549                   ModeIndex = ModeIndex_1024x600[Depth];
 550                }
 551             }
 552             break;
 553        case 1152:
 554             if(VGAEngine == SIS_300_VGA) {
 555                if((VDisplay == 768) && (LCDheight == 768)) {
 556                   ModeIndex = ModeIndex_1152x768[Depth];
 557                }
 558             }
 559             break;
 560        case 1280:
 561             if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 562             else if(VGAEngine == SIS_315_VGA) {
 563                if((VDisplay == 768) && (LCDheight == 768)) {
 564                   ModeIndex = ModeIndex_310_1280x768[Depth];
 565                }
 566             }
 567             break;
 568        case 1360:
 569             if(VGAEngine == SIS_300_VGA) {
 570                if(CustomT == CUT_BARCO1366) {
 571                   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
 572                }
 573             }
 574             if(CustomT == CUT_PANEL848) {
 575                if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
 576             }
 577             break;
 578        case 1400:
 579             if(VGAEngine == SIS_315_VGA) {
 580                if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
 581             }
 582             break;
 583        case 1600:
 584             if(VGAEngine == SIS_315_VGA) {
 585                if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
 586             }
 587             break;
 588      }
 589
 590   } else if(VBFlags2 & VB2_SISBRIDGE) {
 591
 592      switch(HDisplay)
 593      {
 594        case 320:
 595             if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
 596             else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
 597             break;
 598        case 400:
 599             if(LCDwidth >= 800 && LCDheight >= 600) {
 600                if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 601             }
 602             break;
 603        case 512:
 604             if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
 605                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 606             }
 607             break;
 608        case 640:
 609             if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 610             else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 611             break;
 612        case 720:
 613             if(VGAEngine == SIS_315_VGA) {
 614                if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
 615                else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
 616             }
 617             break;
 618        case 768:
 619             if(VGAEngine == SIS_315_VGA) {
 620                if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 621             }
 622             break;
 623        case 800:
 624             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 625             if(VGAEngine == SIS_315_VGA) {
 626                if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
 627             }
 628             break;
 629        case 848:
 630             if(VGAEngine == SIS_315_VGA) {
 631                if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 632             }
 633             break;
 634        case 856:
 635             if(VGAEngine == SIS_315_VGA) {
 636                if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 637             }
 638             break;
 639        case 960:
 640             if(VGAEngine == SIS_315_VGA) {
 641                if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
 642                else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
 643             }
 644             break;
 645        case 1024:
 646             if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
 647             if(VGAEngine == SIS_315_VGA) {
 648                if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
 649             }
 650             break;
 651        case 1152:
 652             if(VGAEngine == SIS_315_VGA) {
 653                if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
 654             }
 655             break;
 656        case 1280:
 657             switch(VDisplay) {
 658             case 720:
 659                ModeIndex = ModeIndex_1280x720[Depth];
 660             case 768:
 661                if(VGAEngine == SIS_300_VGA) {
 662                   ModeIndex = ModeIndex_300_1280x768[Depth];
 663                } else {
 664                   ModeIndex = ModeIndex_310_1280x768[Depth];
 665                }
 666                break;
 667             case 800:
 668                if(VGAEngine == SIS_315_VGA) {
 669                   ModeIndex = ModeIndex_1280x800[Depth];
 670                }
 671                break;
 672             case 854:
 673                if(VGAEngine == SIS_315_VGA) {
 674                   ModeIndex = ModeIndex_1280x854[Depth];
 675                }
 676                break;
 677             case 960:
 678                ModeIndex = ModeIndex_1280x960[Depth];
 679                break;
 680             case 1024:
 681                ModeIndex = ModeIndex_1280x1024[Depth];
 682                break;
 683             }
 684             break;
 685        case 1360:
 686             if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
 687                if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
 688             }
 689             break;
 690        case 1400:
 691             if(VGAEngine == SIS_315_VGA) {
 692                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 693                   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
 694                }
 695             }
 696             break;
 697        case 1600:
 698             if(VGAEngine == SIS_315_VGA) {
 699                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 700                   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
 701                }
 702             }
 703             break;
 704#ifndef VB_FORBID_CRT2LCD_OVER_1600
 705        case 1680:
 706             if(VGAEngine == SIS_315_VGA) {
 707                if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
 708                   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
 709                }
 710             }
 711             break;
 712        case 1920:
 713             if(VGAEngine == SIS_315_VGA) {
 714                if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
 715                   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
 716                }
 717             }
 718             break;
 719        case 2048:
 720             if(VGAEngine == SIS_315_VGA) {
 721                if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
 722                   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
 723                }
 724             }
 725             break;
 726#endif
 727      }
 728   }
 729
 730   return ModeIndex;
 731}
 732
 733unsigned short
 734SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
 735                        unsigned int VBFlags2)
 736{
 737   unsigned short ModeIndex = 0;
 738
 739   if(VBFlags2 & VB2_CHRONTEL) {
 740
 741      switch(HDisplay)
 742      {
 743        case 512:
 744             if(VGAEngine == SIS_315_VGA) {
 745                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 746             }
 747             break;
 748        case 640:
 749             if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 750             else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 751             break;
 752        case 800:
 753             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 754             break;
 755        case 1024:
 756             if(VGAEngine == SIS_315_VGA) {
 757                if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
 758             }
 759             break;
 760      }
 761
 762   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
 763
 764      switch(HDisplay)
 765      {
 766        case 320:
 767             if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
 768             else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
 769             break;
 770        case 400:
 771             if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
 772             break;
 773        case 512:
 774             if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
 775                 (VBFlags & TV_HIVISION)                                              ||
 776                 ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 777                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 778             }
 779             break;
 780        case 640:
 781             if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 782             else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 783             break;
 784        case 720:
 785             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
 786                if(VDisplay == 480) {
 787                   ModeIndex = ModeIndex_720x480[Depth];
 788                } else if(VDisplay == 576) {
 789                   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
 790                       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
 791                      ModeIndex = ModeIndex_720x576[Depth];
 792                }
 793             }
 794             break;
 795        case 768:
 796             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
 797                if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
 798                    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 799                   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 800                }
 801             }
 802             break;
 803        case 800:
 804             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 805             else if(VDisplay == 480) {
 806                if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
 807                   ModeIndex = ModeIndex_800x480[Depth];
 808                }
 809             }
 810             break;
 811        case 960:
 812             if(VGAEngine == SIS_315_VGA) {
 813                if(VDisplay == 600) {
 814                   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 815                      ModeIndex = ModeIndex_960x600[Depth];
 816                   }
 817                }
 818             }
 819             break;
 820        case 1024:
 821             if(VDisplay == 768) {
 822                if(VBFlags2 & VB2_30xBLV) {
 823                   ModeIndex = ModeIndex_1024x768[Depth];
 824                }
 825             } else if(VDisplay == 576) {
 826                if( (VBFlags & TV_HIVISION) ||
 827                    ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
 828                    ((VBFlags2 & VB2_30xBLV) &&
 829                     ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
 830                   ModeIndex = ModeIndex_1024x576[Depth];
 831                }
 832             }
 833             break;
 834        case 1280:
 835             if(VDisplay == 720) {
 836                if((VBFlags & TV_HIVISION) ||
 837                   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
 838                   ModeIndex = ModeIndex_1280x720[Depth];
 839                }
 840             } else if(VDisplay == 1024) {
 841                if((VBFlags & TV_HIVISION) ||
 842                   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 843                   ModeIndex = ModeIndex_1280x1024[Depth];
 844                }
 845             }
 846             break;
 847      }
 848   }
 849   return ModeIndex;
 850}
 851
 852unsigned short
 853SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
 854                        unsigned int VBFlags2)
 855{
 856   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
 857
 858   if(HDisplay >= 1920) return 0;
 859
 860   switch(HDisplay)
 861   {
 862        case 1600:
 863                if(VDisplay == 1200) {
 864                        if(VGAEngine != SIS_315_VGA) return 0;
 865                        if(!(VBFlags2 & VB2_30xB)) return 0;
 866                }
 867                break;
 868        case 1680:
 869                if(VDisplay == 1050) {
 870                        if(VGAEngine != SIS_315_VGA) return 0;
 871                        if(!(VBFlags2 & VB2_30xB)) return 0;
 872                }
 873                break;
 874   }
 875
 876   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
 877}
 878
 879
 880/*********************************************/
 881/*          HELPER: SetReg, GetReg           */
 882/*********************************************/
 883
 884void
 885SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
 886{
 887   OutPortByte(port, index);
 888   OutPortByte(port + 1, data);
 889}
 890
 891void
 892SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
 893{
 894   OutPortByte(port, data);
 895}
 896
 897void
 898SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
 899{
 900   OutPortWord(port, data);
 901}
 902
 903void
 904SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
 905{
 906   OutPortLong(port, data);
 907}
 908
 909unsigned char
 910SiS_GetReg(SISIOADDRESS port, unsigned short index)
 911{
 912   OutPortByte(port, index);
 913   return(InPortByte(port + 1));
 914}
 915
 916unsigned char
 917SiS_GetRegByte(SISIOADDRESS port)
 918{
 919   return(InPortByte(port));
 920}
 921
 922unsigned short
 923SiS_GetRegShort(SISIOADDRESS port)
 924{
 925   return(InPortWord(port));
 926}
 927
 928unsigned int
 929SiS_GetRegLong(SISIOADDRESS port)
 930{
 931   return(InPortLong(port));
 932}
 933
 934void
 935SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
 936{
 937   unsigned short temp;
 938
 939   temp = SiS_GetReg(Port, Index);
 940   temp = (temp & (DataAND)) | DataOR;
 941   SiS_SetReg(Port, Index, temp);
 942}
 943
 944void
 945SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
 946{
 947   unsigned short temp;
 948
 949   temp = SiS_GetReg(Port, Index);
 950   temp &= DataAND;
 951   SiS_SetReg(Port, Index, temp);
 952}
 953
 954void
 955SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
 956{
 957   unsigned short temp;
 958
 959   temp = SiS_GetReg(Port, Index);
 960   temp |= DataOR;
 961   SiS_SetReg(Port, Index, temp);
 962}
 963
 964/*********************************************/
 965/*      HELPER: DisplayOn, DisplayOff        */
 966/*********************************************/
 967
 968void
 969SiS_DisplayOn(struct SiS_Private *SiS_Pr)
 970{
 971   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 972}
 973
 974void
 975SiS_DisplayOff(struct SiS_Private *SiS_Pr)
 976{
 977   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 978}
 979
 980
 981/*********************************************/
 982/*        HELPER: Init Port Addresses        */
 983/*********************************************/
 984
 985void
 986SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
 987{
 988   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
 989   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
 990   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
 991   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
 992   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
 993   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
 994   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
 995   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
 996   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
 997   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
 998   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
 999   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
1000   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
1001   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
1002   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
1003   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
1004   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
1005   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
1006   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
1007   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
1008   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
1009   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
1010}
1011
1012/*********************************************/
1013/*             HELPER: GetSysFlags           */
1014/*********************************************/
1015
1016static void
1017SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
1018{
1019   unsigned char cr5f, temp1, temp2;
1020
1021   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
1022   /* (SR11 is used for DDC and in enable/disablebridge) */
1023   SiS_Pr->SiS_SensibleSR11 = false;
1024   SiS_Pr->SiS_MyCR63 = 0x63;
1025   if(SiS_Pr->ChipType >= SIS_330) {
1026      SiS_Pr->SiS_MyCR63 = 0x53;
1027      if(SiS_Pr->ChipType >= SIS_661) {
1028         SiS_Pr->SiS_SensibleSR11 = true;
1029      }
1030   }
1031
1032   /* You should use the macros, not these flags directly */
1033
1034   SiS_Pr->SiS_SysFlags = 0;
1035   if(SiS_Pr->ChipType == SIS_650) {
1036      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
1037      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
1038      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1039      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
1040      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1041      if((!temp1) || (temp2)) {
1042         switch(cr5f) {
1043            case 0x80:
1044            case 0x90:
1045            case 0xc0:
1046               SiS_Pr->SiS_SysFlags |= SF_IsM650;
1047               break;
1048            case 0xa0:
1049            case 0xb0:
1050            case 0xe0:
1051               SiS_Pr->SiS_SysFlags |= SF_Is651;
1052               break;
1053         }
1054      } else {
1055         switch(cr5f) {
1056            case 0x90:
1057               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1058               switch(temp1) {
1059                  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
1060                  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
1061                  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
1062               }
1063               break;
1064            case 0xb0:
1065               SiS_Pr->SiS_SysFlags |= SF_Is652;
1066               break;
1067            default:
1068               SiS_Pr->SiS_SysFlags |= SF_IsM650;
1069               break;
1070         }
1071      }
1072   }
1073
1074   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
1075      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
1076         SiS_Pr->SiS_SysFlags |= SF_760LFB;
1077      }
1078      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
1079         SiS_Pr->SiS_SysFlags |= SF_760UMA;
1080      }
1081   }
1082}
1083
1084/*********************************************/
1085/*         HELPER: Init PCI & Engines        */
1086/*********************************************/
1087
1088static void
1089SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1090{
1091   switch(SiS_Pr->ChipType) {
1092#ifdef SIS300
1093   case SIS_300:
1094   case SIS_540:
1095   case SIS_630:
1096   case SIS_730:
1097      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
1098       *     - RELOCATED VGA IO ENABLED (0x20)
1099       *     - MMIO ENABLED (0x01)
1100       * Leave other bits untouched.
1101       */
1102      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1103      /*  - Enable 2D (0x40)
1104       *  - Enable 3D (0x02)
1105       *  - Enable 3D Vertex command fetch (0x10) ?
1106       *  - Enable 3D command parser (0x08) ?
1107       */
1108      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
1109      break;
1110#endif
1111#ifdef SIS315H
1112   case SIS_315H:
1113   case SIS_315:
1114   case SIS_315PRO:
1115   case SIS_650:
1116   case SIS_740:
1117   case SIS_330:
1118   case SIS_661:
1119   case SIS_741:
1120   case SIS_660:
1121   case SIS_760:
1122   case SIS_761:
1123   case SIS_340:
1124   case XGI_40:
1125      /* See above */
1126      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1127      /*  - Enable 3D G/L transformation engine (0x80)
1128       *  - Enable 2D (0x40)
1129       *  - Enable 3D vertex command fetch (0x10)
1130       *  - Enable 3D command parser (0x08)
1131       *  - Enable 3D (0x02)
1132       */
1133      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
1134      break;
1135   case XGI_20:
1136   case SIS_550:
1137      /* See above */
1138      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1139      /* No 3D engine ! */
1140      /*  - Enable 2D (0x40)
1141       *  - disable 3D
1142       */
1143      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
1144      break;
1145#endif
1146   default:
1147      break;
1148   }
1149}
1150
1151/*********************************************/
1152/*             HELPER: SetLVDSetc            */
1153/*********************************************/
1154
1155#ifdef SIS_LINUX_KERNEL
1156static
1157#endif
1158void
1159SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1160{
1161   unsigned short temp;
1162
1163   SiS_Pr->SiS_IF_DEF_LVDS = 0;
1164   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
1165   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
1166   SiS_Pr->SiS_IF_DEF_CONEX = 0;
1167
1168   SiS_Pr->SiS_ChrontelInit = 0;
1169
1170   if(SiS_Pr->ChipType == XGI_20) return;
1171
1172   /* Check for SiS30x first */
1173   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1174   if((temp == 1) || (temp == 2)) return;
1175
1176   switch(SiS_Pr->ChipType) {
1177#ifdef SIS300
1178   case SIS_540:
1179   case SIS_630:
1180   case SIS_730:
1181        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1182        if((temp >= 2) && (temp <= 5))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1183        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
1184        if((temp == 4) || (temp == 5)) {
1185                /* Save power status (and error check) - UNUSED */
1186                SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
1187                SiS_Pr->SiS_IF_DEF_CH70xx = 1;
1188        }
1189        break;
1190#endif
1191#ifdef SIS315H
1192   case SIS_550:
1193   case SIS_650:
1194   case SIS_740:
1195   case SIS_330:
1196        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1197        if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1198        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1199        break;
1200   case SIS_661:
1201   case SIS_741:
1202   case SIS_660:
1203   case SIS_760:
1204   case SIS_761:
1205   case SIS_340:
1206   case XGI_20:
1207   case XGI_40:
1208        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
1209        if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
1210        if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1211        if(temp == 4)                   SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
1212        break;
1213#endif
1214   default:
1215        break;
1216   }
1217}
1218
1219/*********************************************/
1220/*          HELPER: Enable DSTN/FSTN         */
1221/*********************************************/
1222
1223void
1224SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
1225{
1226   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
1227}
1228
1229void
1230SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
1231{
1232   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
1233}
1234
1235/*********************************************/
1236/*            HELPER: Get modeflag           */
1237/*********************************************/
1238
1239unsigned short
1240SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1241                unsigned short ModeIdIndex)
1242{
1243   if(SiS_Pr->UseCustomMode) {
1244      return SiS_Pr->CModeFlag;
1245   } else if(ModeNo <= 0x13) {
1246      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1247   } else {
1248      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1249   }
1250}
1251
1252/*********************************************/
1253/*        HELPER: Determine ROM usage        */
1254/*********************************************/
1255
1256bool
1257SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
1258{
1259   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
1260   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
1261
1262   if(SiS_Pr->ChipType >= XGI_20) {
1263      /* XGI ROMs don't qualify */
1264      return false;
1265   } else if(SiS_Pr->ChipType >= SIS_761) {
1266      /* I very much assume 761, 340 and newer will use new layout */
1267      return true;
1268   } else if(SiS_Pr->ChipType >= SIS_661) {
1269      if((ROMAddr[0x1a] == 'N') &&
1270         (ROMAddr[0x1b] == 'e') &&
1271         (ROMAddr[0x1c] == 'w') &&
1272         (ROMAddr[0x1d] == 'V')) {
1273         return true;
1274      }
1275      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
1276      if(romversoffs) {
1277         if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
1278            romvmaj = ROMAddr[romversoffs] - '0';
1279            romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
1280         }
1281      }
1282      if((romvmaj != 0) || (romvmin >= 92)) {
1283         return true;
1284      }
1285   } else if(IS_SIS650740) {
1286      if((ROMAddr[0x1a] == 'N') &&
1287         (ROMAddr[0x1b] == 'e') &&
1288         (ROMAddr[0x1c] == 'w') &&
1289         (ROMAddr[0x1d] == 'V')) {
1290         return true;
1291      }
1292   }
1293   return false;
1294}
1295
1296static void
1297SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
1298{
1299   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
1300   unsigned short romptr = 0;
1301
1302   SiS_Pr->SiS_UseROM = false;
1303   SiS_Pr->SiS_ROMNew = false;
1304   SiS_Pr->SiS_PWDOffset = 0;
1305
1306   if(SiS_Pr->ChipType >= XGI_20) return;
1307
1308   if((ROMAddr) && (SiS_Pr->UseROM)) {
1309      if(SiS_Pr->ChipType == SIS_300) {
1310         /* 300: We check if the code starts below 0x220 by
1311          * checking the jmp instruction at the beginning
1312          * of the BIOS image.
1313          */
1314         if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
1315            SiS_Pr->SiS_UseROM = true;
1316      } else if(SiS_Pr->ChipType < SIS_315H) {
1317         /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
1318          * the others do as well
1319          */
1320         SiS_Pr->SiS_UseROM = true;
1321      } else {
1322         /* 315/330 series stick to the standard(s) */
1323         SiS_Pr->SiS_UseROM = true;
1324         if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
1325            SiS_Pr->SiS_EMIOffset = 14;
1326            SiS_Pr->SiS_PWDOffset = 17;
1327            SiS_Pr->SiS661LCD2TableSize = 36;
1328            /* Find out about LCD data table entry size */
1329            if((romptr = SISGETROMW(0x0102))) {
1330               if(ROMAddr[romptr + (32 * 16)] == 0xff)
1331                  SiS_Pr->SiS661LCD2TableSize = 32;
1332               else if(ROMAddr[romptr + (34 * 16)] == 0xff)
1333                  SiS_Pr->SiS661LCD2TableSize = 34;
1334               else if(ROMAddr[romptr + (36 * 16)] == 0xff)        /* 0.94, 2.05.00+ */
1335                  SiS_Pr->SiS661LCD2TableSize = 36;
1336               else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
1337                        (ROMAddr[0x6F] & 0x01) ) {                 /* 2.03.00 - <2.05.00 */
1338                  SiS_Pr->SiS661LCD2TableSize = 38;                /* UMC data layout abandoned at 2.05.00 */
1339                  SiS_Pr->SiS_EMIOffset = 16;
1340                  SiS_Pr->SiS_PWDOffset = 19;
1341               }
1342            }
1343         }
1344      }
1345   }
1346}
1347
1348/*********************************************/
1349/*        HELPER: SET SEGMENT REGISTERS      */
1350/*********************************************/
1351
1352static void
1353SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
1354{
1355   unsigned short temp;
1356
1357   value &= 0x00ff;
1358   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
1359   temp |= (value >> 4);
1360   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1361   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
1362   temp |= (value & 0x0f);
1363   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1364}
1365
1366static void
1367SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
1368{
1369   unsigned short temp;
1370
1371   value &= 0x00ff;
1372   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
1373   temp |= (value & 0xf0);
1374   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1375   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
1376   temp |= (value << 4);
1377   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1378}
1379
1380static void
1381SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
1382{
1383   SiS_SetSegRegLower(SiS_Pr, value);
1384   SiS_SetSegRegUpper(SiS_Pr, value);
1385}
1386
1387static void
1388SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
1389{
1390   SiS_SetSegmentReg(SiS_Pr, 0);
1391}
1392
1393static void
1394SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
1395{
1396   unsigned short temp = value >> 8;
1397
1398   temp &= 0x07;
1399   temp |= (temp << 4);
1400   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
1401   SiS_SetSegmentReg(SiS_Pr, value);
1402}
1403
1404static void
1405SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
1406{
1407   SiS_SetSegmentRegOver(SiS_Pr, 0);
1408}
1409
1410static void
1411SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
1412{
1413   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
1414      SiS_ResetSegmentReg(SiS_Pr);
1415      SiS_ResetSegmentRegOver(SiS_Pr);
1416   }
1417}
1418
1419/*********************************************/
1420/*             HELPER: GetVBType             */
1421/*********************************************/
1422
1423#ifdef SIS_LINUX_KERNEL
1424static
1425#endif
1426void
1427SiS_GetVBType(struct SiS_Private *SiS_Pr)
1428{
1429   unsigned short flag = 0, rev = 0, nolcd = 0;
1430   unsigned short p4_0f, p4_25, p4_27;
1431
1432   SiS_Pr->SiS_VBType = 0;
1433
1434   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
1435      return;
1436
1437   if(SiS_Pr->ChipType == XGI_20)
1438      return;
1439
1440   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1441
1442   if(flag > 3)
1443      return;
1444
1445   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
1446
1447   if(flag >= 2) {
1448      SiS_Pr->SiS_VBType = VB_SIS302B;
1449   } else if(flag == 1) {
1450      if(rev >= 0xC0) {
1451         SiS_Pr->SiS_VBType = VB_SIS301C;
1452      } else if(rev >= 0xB0) {
1453         SiS_Pr->SiS_VBType = VB_SIS301B;
1454         /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
1455         nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
1456         if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
1457      } else {
1458         SiS_Pr->SiS_VBType = VB_SIS301;
1459      }
1460   }
1461   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
1462      if(rev >= 0xE0) {
1463         flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
1464         if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
1465         else             SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
1466      } else if(rev >= 0xD0) {
1467         SiS_Pr->SiS_VBType = VB_SIS301LV;
1468      }
1469   }
1470   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
1471      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
1472      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
1473      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
1474      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
1475      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
1476      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
1477      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
1478         SiS_Pr->SiS_VBType |= VB_UMC;
1479      }
1480      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
1481      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
1482      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
1483   }
1484}
1485
1486/*********************************************/
1487/*           HELPER: Check RAM size          */
1488/*********************************************/
1489
1490#ifdef SIS_LINUX_KERNEL
1491static bool
1492SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1493                unsigned short ModeIdIndex)
1494{
1495   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
1496   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1497   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
1498
1499   if(!AdapterMemSize) return true;
1500
1501   if(AdapterMemSize < memorysize) return false;
1502   return true;
1503}
1504#endif
1505
1506/*********************************************/
1507/*           HELPER: Get DRAM type           */
1508/*********************************************/
1509
1510#ifdef SIS315H
1511static unsigned char
1512SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
1513{
1514   unsigned char data;
1515
1516   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
1517      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
1518   } else {
1519      if(SiS_Pr->ChipType >= XGI_20) {
1520         /* Do I need this? SR17 seems to be zero anyway... */
1521         data = 0;
1522      } else if(SiS_Pr->ChipType >= SIS_340) {
1523         /* TODO */
1524         data = 0;
1525      } if(SiS_Pr->ChipType >= SIS_661) {
1526         if(SiS_Pr->SiS_ROMNew) {
1527            data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
1528         } else {
1529            data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
1530         }
1531      } else if(IS_SIS550650740) {
1532         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
1533      } else {  /* 315, 330 */
1534         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
1535         if(SiS_Pr->ChipType == SIS_330) {
1536            if(data > 1) {
1537               switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
1538               case 0x00: data = 1; break;
1539               case 0x10: data = 3; break;
1540               case 0x20: data = 3; break;
1541               case 0x30: data = 2; break;
1542               }
1543            } else {
1544               data = 0;
1545            }
1546         }
1547      }
1548   }
1549
1550   return data;
1551}
1552
1553static unsigned short
1554SiS_GetMCLK(struct SiS_Private *SiS_Pr)
1555{
1556   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
1557   unsigned short index;
1558
1559   index = SiS_Get310DRAMType(SiS_Pr);
1560   if(SiS_Pr->ChipType >= SIS_661) {
1561      if(SiS_Pr->SiS_ROMNew) {
1562         return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
1563      }
1564      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1565   } else if(index >= 4) {
1566      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
1567   } else {
1568      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1569   }
1570}
1571#endif
1572
1573/*********************************************/
1574/*           HELPER: ClearBuffer             */
1575/*********************************************/
1576
1577#ifdef SIS_LINUX_KERNEL
1578static void
1579SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1580{
1581   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
1582   unsigned int   memsize = SiS_Pr->VideoMemorySize;
1583   unsigned short SISIOMEMTYPE *pBuffer;
1584   int i;
1585
1586   if(!memaddr || !memsize) return;
1587
1588   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
1589      if(ModeNo > 0x13) {
1590         SiS_SetMemory(memaddr, memsize, 0);
1591      } else {
1592         pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1593         for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
1594      }
1595   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
1596      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1597      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
1598   } else {
1599      SiS_SetMemory(memaddr, 0x8000, 0);
1600   }
1601}
1602#endif
1603
1604/*********************************************/
1605/*           HELPER: SearchModeID            */
1606/*********************************************/
1607
1608bool
1609SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
1610                unsigned short *ModeIdIndex)
1611{
1612   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
1613
1614   if((*ModeNo) <= 0x13) {
1615
1616      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
1617
1618      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1619         if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
1620         if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
1621      }
1622
1623      if((*ModeNo) == 0x07) {
1624          if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
1625          /* else 350 lines */
1626      }
1627      if((*ModeNo) <= 0x03) {
1628         if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
1629         if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
1630         /* else 350 lines  */
1631      }
1632      /* else 200 lines  */
1633
1634   } else {
1635
1636      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1637         if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
1638         if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
1639      }
1640
1641   }
1642   return true;
1643}
1644
1645/*********************************************/
1646/*            HELPER: GetModePtr             */
1647/*********************************************/
1648
1649unsigned short
1650SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1651{
1652   unsigned short index;
1653
1654   if(ModeNo <= 0x13) {
1655      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
1656   } else {
1657      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
1658      else index = 0x0F;
1659   }
1660   return index;
1661}
1662
1663/*********************************************/
1664/*         HELPERS: Get some indices         */
1665/*********************************************/
1666
1667unsigned short
1668SiS_GetRefCRTVCLK(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_CRTVCLK_WIDE;
1673      } else {
1674         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
1675      }
1676   } else {
1677      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
1678   }
1679}
1680
1681unsigned short
1682SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
1683{
1684   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
1685      if(UseWide == 1) {
1686         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
1687      } else {
1688         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
1689      }
1690   } else {
1691      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
1692   }
1693}
1694
1695/*********************************************/
1696/*           HELPER: LowModeTests            */
1697/*********************************************/
1698
1699static bool
1700SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1701{
1702   unsigned short temp, temp1, temp2;
1703
1704   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
1705      return true;
1706   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
1707   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
1708   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1709   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
1710   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1711   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
1712   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
1713   if((SiS_Pr->ChipType >= SIS_315H) ||
1714      (SiS_Pr->ChipType == SIS_300)) {
1715      if(temp2 == 0x55) return false;
1716      else return true;
1717   } else {
1718      if(temp2 != 0x55) return true;
1719      else {
1720         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
1721         return false;
1722      }
1723   }
1724}
1725
1726static void
1727SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1728{
1729   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
1730      SiS_Pr->SiS_SetFlag |= LowModeTests;
1731   }
1732}
1733
1734/*********************************************/
1735/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
1736/*********************************************/
1737
1738static void
1739SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
1740{
1741   if(IS_SIS650) {
1742      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1743      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
1744      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1745   } else if(IS_SIS661741660760) {
1746      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
1747      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1748      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1749      if(!SiS_Pr->SiS_ROMNew) {
1750         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
1751      }
1752   }
1753}
1754
1755static void
1756SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
1757{
1758#if 0 /* This locks some CRTC registers. We don't want that. */
1759   unsigned short temp1 = 0, temp2 = 0;
1760
1761   if(IS_SIS661741660760) {
1762      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1763         temp1 = 0xa0; temp2 = 0x08;
1764      }
1765      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
1766      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
1767   }
1768#endif
1769}
1770
1771static void
1772SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
1773{
1774   /* Enable CRT1 gating */
1775   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
1776#if 0
1777   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
1778      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
1779         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
1780         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
1781      }
1782   }
1783#endif
1784}
1785
1786/*********************************************/
1787/*           HELPER: GetColorDepth           */
1788/*********************************************/
1789
1790unsigned short
1791SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1792                unsigned short ModeIdIndex)
1793{
1794   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
1795   unsigned short modeflag;
1796   short index;
1797
1798   /* Do NOT check UseCustomMode, will skrew up FIFO */
1799   if(ModeNo == 0xfe) {
1800      modeflag = SiS_Pr->CModeFlag;
1801   } else if(ModeNo <= 0x13) {
1802      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1803   } else {
1804      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1805   }
1806
1807   index = (modeflag & ModeTypeMask) - ModeEGA;
1808   if(index < 0) index = 0;
1809   return ColorDepth[index];
1810}
1811
1812/*********************************************/
1813/*             HELPER: GetOffset             */
1814/*********************************************/
1815
1816unsigned short
1817SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1818                unsigned short ModeIdIndex, unsigned short RRTI)
1819{
1820   unsigned short xres, temp, colordepth, infoflag;
1821
1822   if(SiS_Pr->UseCustomMode) {
1823      infoflag = SiS_Pr->CInfoFlag;
1824      xres = SiS_Pr->CHDisplay;
1825   } else {
1826      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
1827      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
1828   }
1829
1830   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
1831
1832   temp = xres / 16;
1833   if(infoflag & InterlaceMode) temp <<= 1;
1834   temp *= colordepth;
1835   if(xres % 16) temp += (colordepth >> 1);
1836
1837   return temp;
1838}
1839
1840/*********************************************/
1841/*                   SEQ                     */
1842/*********************************************/
1843
1844static void
1845SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1846{
1847   unsigned char SRdata;
1848   int i;
1849
1850   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
1851
1852   /* or "display off"  */
1853   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
1854
1855   /* determine whether to force x8 dotclock */
1856   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
1857
1858      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1859         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
1860      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
1861
1862   }
1863
1864   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
1865
1866   for(i = 2; i <= 4; i++) {
1867      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
1868      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
1869   }
1870}
1871
1872/*********************************************/
1873/*                  MISC                     */
1874/*********************************************/
1875
1876static void
1877SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1878{
1879   unsigned char Miscdata;
1880
1881   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
1882
1883   if(SiS_Pr->ChipType < SIS_661) {
1884      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1885         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1886           Miscdata |= 0x0C;
1887         }
1888      }
1889   }
1890
1891   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
1892}
1893
1894/*********************************************/
1895/*                  CRTC                     */
1896/*********************************************/
1897
1898static void
1899SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1900{
1901   unsigned char  CRTCdata;
1902   unsigned short i;
1903
1904   /* Unlock CRTC */
1905   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
1906
1907   for(i = 0; i <= 0x18; i++) {
1908      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1909      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1910   }
1911
1912   if(SiS_Pr->ChipType >= SIS_661) {
1913      SiS_OpenCRTC(SiS_Pr);
1914      for(i = 0x13; i <= 0x14; i++) {
1915         CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1916         SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1917      }
1918   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
1919                (SiS_Pr->ChipType == SIS_730) )  &&
1920              (SiS_Pr->ChipRevision >= 0x30) ) {
1921      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1922         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1923            SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
1924         }
1925      }
1926   }
1927}
1928
1929/*********************************************/
1930/*                   ATT                     */
1931/*********************************************/
1932
1933static void
1934SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1935{
1936   unsigned char  ARdata;
1937   unsigned short i;
1938
1939   for(i = 0; i <= 0x13; i++) {
1940      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
1941
1942      if(i == 0x13) {
1943         /* Pixel shift. If screen on LCD or TV is shifted left or right,
1944          * this might be the cause.
1945          */
1946         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1947            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
1948         }
1949         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1950            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1951               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1952                  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1953               }
1954            }
1955         }
1956         if(SiS_Pr->ChipType >= SIS_661) {
1957            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
1958               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1959            }
1960         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
1961            if(SiS_Pr->ChipType >= SIS_315H) {
1962               if(IS_SIS550650740660) {
1963                  /* 315, 330 don't do this */
1964                  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1965                     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1966                  } else {
1967                     ARdata = 0;
1968                  }
1969               }
1970            } else {
1971               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1972            }
1973         }
1974      }
1975      SiS_GetRegByte(SiS_Pr->SiS_P3da);         /* reset 3da  */
1976      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);       /* set index  */
1977      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);  /* set data   */
1978   }
1979
1980   SiS_GetRegByte(SiS_Pr->SiS_P3da);            /* reset 3da  */
1981   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);       /* set index  */
1982   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);       /* set data   */
1983
1984   SiS_GetRegByte(SiS_Pr->SiS_P3da);
1985   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);       /* Enable Attribute  */
1986   SiS_GetRegByte(SiS_Pr->SiS_P3da);
1987}
1988
1989/*********************************************/
1990/*                   GRC                     */
1991/*********************************************/
1992
1993static void
1994SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1995{
1996   unsigned char  GRdata;
1997   unsigned short i;
1998
1999   for(i = 0; i <= 0x08; i++) {
2000      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
2001      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
2002   }
2003
2004   if(SiS_Pr->SiS_ModeType > ModeVGA) {
2005      /* 256 color disable */
2006      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
2007   }
2008}
2009
2010/*********************************************/
2011/*          CLEAR EXTENDED REGISTERS         */
2012/*********************************************/
2013
2014static void
2015SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
2016{
2017   unsigned short i;
2018
2019   for(i = 0x0A; i <= 0x0E; i++) {
2020      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
2021   }
2022
2023   if(SiS_Pr->ChipType >= SIS_315H) {
2024      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
2025      if(ModeNo <= 0x13) {
2026         if(ModeNo == 0x06 || ModeNo >= 0x0e) {
2027            SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
2028         }
2029      }
2030   }
2031}
2032
2033/*********************************************/
2034/*                 RESET VCLK                */
2035/*********************************************/
2036
2037static void
2038SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
2039{
2040   if(SiS_Pr->ChipType >= SIS_315H) {
2041      if(SiS_Pr->ChipType < SIS_661) {
2042         if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
2043      }
2044   } else {
2045      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
2046         (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
2047         return;
2048      }
2049   }
2050
2051   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
2052   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
2053   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
2054   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2055   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
2056   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
2057   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
2058   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2059}
2060
2061/*********************************************/
2062/*                  SYNC                     */
2063/*********************************************/
2064
2065static void
2066SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
2067{
2068   unsigned short sync;
2069
2070   if(SiS_Pr->UseCustomMode) {
2071      sync = SiS_Pr->CInfoFlag >> 8;
2072   } else {
2073      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
2074   }
2075
2076   sync &= 0xC0;
2077   sync |= 0x2f;
2078   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
2079}
2080
2081/*********************************************/
2082/*                  CRTC/2                   */
2083/*********************************************/
2084
2085static void
2086SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2087                unsigned short ModeIdIndex, unsigned short RRTI)
2088{
2089   unsigned short temp, i, j, modeflag;
2090   unsigned char  *crt1data = NULL;
2091
2092   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2093
2094   if(SiS_Pr->UseCustomMode) {
2095
2096      crt1data = &SiS_Pr->CCRT1CRTC[0];
2097
2098   } else {
2099
2100      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
2101
2102      /* Alternate for 1600x1200 LCDA */
2103      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
2104
2105      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
2106
2107   }
2108
2109   /* unlock cr0-7 */
2110   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
2111
2112   for(i = 0, j = 0; i <= 7; i++, j++) {
2113      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2114   }
2115   for(j = 0x10; i <= 10; i++, j++) {
2116      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2117   }
2118   for(j = 0x15; i <= 12; i++, j++) {
2119      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2120   }
2121   for(j = 0x0A; i <= 15; i++, j++) {
2122      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
2123   }
2124
2125   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
2126
2127   temp = (crt1data[16] & 0x01) << 5;
2128   if(modeflag & DoubleScanMode) temp |= 0x80;
2129   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
2130
2131   if(SiS_Pr->SiS_ModeType > ModeVGA) {
2132      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
2133   }
2134
2135#ifdef SIS315H
2136   if(SiS_Pr->ChipType == XGI_20) {
2137      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
2138      if(!(temp = crt1data[5] & 0x1f)) {
2139         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
2140      }
2141      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
2142      temp = (crt1data[16] >> 5) + 3;
2143      if(temp > 7) temp -= 7;
2144      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
2145   }
2146#endif
2147}
2148
2149/*********************************************/
2150/*               OFFSET & PITCH              */
2151/*********************************************/
2152/*  (partly overruled by SetPitch() in XF86) */
2153/*********************************************/
2154
2155static void
2156SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2157                unsigned short ModeIdIndex, unsigned short RRTI)
2158{
2159   unsigned short temp, DisplayUnit, infoflag;
2160
2161   if(SiS_Pr->UseCustomMode) {
2162      infoflag = SiS_Pr->CInfoFlag;
2163   } else {
2164      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2165   }
2166
2167   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2168
2169   temp = (DisplayUnit >> 8) & 0x0f;
2170   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
2171
2172   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
2173
2174   if(infoflag & InterlaceMode) DisplayUnit >>= 1;
2175
2176   DisplayUnit <<= 5;
2177   temp = (DisplayUnit >> 8) + 1;
2178   if(DisplayUnit & 0xff) temp++;
2179   if(SiS_Pr->ChipType == XGI_20) {
2180      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
2181   }
2182   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
2183}
2184
2185/*********************************************/
2186/*                  VCLK                     */
2187/*********************************************/
2188
2189static void
2190SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2191                unsigned short ModeIdIndex, unsigned short RRTI)
2192{
2193   unsigned short index = 0, clka, clkb;
2194
2195   if(SiS_Pr->UseCustomMode) {
2196      clka = SiS_Pr->CSR2B;
2197      clkb = SiS_Pr->CSR2C;
2198   } else {
2199      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2200      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
2201         (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2202         /* Alternate for 1600x1200 LCDA */
2203         if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
2204         clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
2205         clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
2206      } else {
2207         clka = SiS_Pr->SiS_VCLKData[index].SR2B;
2208         clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
2209      }
2210   }
2211
2212   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
2213
2214   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
2215   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2216
2217   if(SiS_Pr->ChipType >= SIS_315H) {
2218#ifdef SIS315H
2219      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
2220      if(SiS_Pr->ChipType == XGI_20) {
2221         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2222         if(mf & HalfDCLK) {
2223            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
2224            clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
2225            clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
2226            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2227         }
2228      }
2229#endif
2230   } else {
2231      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2232   }
2233}
2234
2235/*********************************************/
2236/*                  FIFO                     */
2237/*********************************************/
2238
2239#ifdef SIS300
2240void
2241SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
2242                unsigned short *idx2)
2243{
2244   unsigned short temp1, temp2;
2245   static const unsigned char ThTiming[8] = {
2246                1, 2, 2, 3, 0, 1, 1, 2
2247   };
2248
2249   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
2250   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
2251   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
2252   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
2253   (*idx1) <<= 1;
2254}
2255
2256static unsigned short
2257SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
2258{
2259   static const unsigned char ThLowA[8 * 3] = {
2260                61, 3,52, 5,68, 7,100,11,
2261                43, 3,42, 5,54, 7, 78,11,
2262                34, 3,37, 5,47, 7, 67,11
2263   };
2264
2265   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
2266}
2267
2268unsigned short
2269SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
2270{
2271   static const unsigned char ThLowB[8 * 3] = {
2272                81, 4,72, 6,88, 8,120,12,
2273                55, 4,54, 6,66, 8, 90,12,
2274                42, 4,45, 6,55, 8, 75,12
2275   };
2276
2277   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
2278}
2279
2280static unsigned short
2281SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
2282                unsigned short colordepth, unsigned short key)
2283{
2284   unsigned short idx1, idx2;
2285   unsigned int   longtemp = VCLK * colordepth;
2286
2287   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
2288
2289   if(key == 0) {
2290      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
2291   } else {
2292      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
2293   }
2294   idx1 = longtemp % (MCLK * 16);
2295   longtemp /= (MCLK * 16);
2296   if(idx1) longtemp++;
2297   return (unsigned short)longtemp;
2298}
2299
2300static unsigned short
2301SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
2302                unsigned short colordepth, unsigned short MCLK)
2303{
2304   unsigned short temp1, temp2;
2305
2306   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
2307   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
2308   if(temp1 < 4) temp1 = 4;
2309   temp1 -= 4;
2310   if(temp2 < temp1) temp2 = temp1;
2311   return temp2;
2312}
2313
2314static void
2315SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2316                unsigned short RefreshRateTableIndex)
2317{
2318   unsigned short ThresholdLow = 0;
2319   unsigned short temp, index, VCLK, MCLK, colorth;
2320   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
2321
2322   if(ModeNo > 0x13) {
2323
2324      /* Get VCLK  */
2325      if(SiS_Pr->UseCustomMode) {
2326         VCLK = SiS_Pr->CSRClock;
2327      } else {
2328         index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2329         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2330      }
2331
2332      /* Get half colordepth */
2333      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2334
2335      /* Get MCLK  */
2336      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
2337      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
2338
2339      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
2340      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
2341
2342      do {
2343         ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
2344         if(ThresholdLow < 0x13) break;
2345         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
2346         ThresholdLow = 0x13;
2347         temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
2348         if(!temp) break;
2349         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
2350      } while(0);
2351
2352   } else ThresholdLow = 2;
2353
2354   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2355   temp = (ThresholdLow << 4) | 0x0f;
2356   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
2357
2358   temp = (ThresholdLow & 0x10) << 1;
2359   if(ModeNo > 0x13) temp |= 0x40;
2360   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
2361
2362   /* What is this? */
2363   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2364
2365   /* Write CRT/CPU threshold high */
2366   temp = ThresholdLow + 3;
2367   if(temp > 0x0f) temp = 0x0f;
2368   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
2369}
2370
2371unsigned short
2372SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
2373{
2374   static const unsigned char LatencyFactor[] = {
2375                97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
2376                 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
2377                97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
2378                 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
2379                80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
2380                 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
2381                86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
2382                 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
2383   };
2384   static const unsigned char LatencyFactor730[] = {
2385                 69, 63, 61,
2386                 86, 79, 77,
2387                103, 96, 94,
2388                120,113,111,
2389                137,130,128
2390   };
2391
2392   if(SiS_Pr->ChipType == SIS_730) {
2393      return (unsigned short)LatencyFactor730[index];
2394   } else {
2395      return (unsigned short)LatencyFactor[index];
2396   }
2397}
2398
2399static unsigned short
2400SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
2401{
2402   unsigned short index;
2403
2404   if(SiS_Pr->ChipType == SIS_730) {
2405      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
2406   } else {
2407      index = (key & 0xe0) >> 5;
2408      if(key & 0x10)    index +=  6;
2409      if(!(key & 0x01)) index += 24;
2410      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
2411   }
2412   return SiS_GetLatencyFactor630(SiS_Pr, index);
2413}
2414
2415static void
2416SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2417                    unsigned short RefreshRateTableIndex)
2418{
2419   unsigned short  ThresholdLow = 0;
2420   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
2421   unsigned int    templ, datal;
2422   const unsigned char *queuedata = NULL;
2423   static const unsigned char FQBQData[21] = {
2424                0x01,0x21,0x41,0x61,0x81,
2425                0x31,0x51,0x71,0x91,0xb1,
2426                0x00,0x20,0x40,0x60,0x80,
2427                0x30,0x50,0x70,0x90,0xb0,
2428                0xff
2429   };
2430   static const unsigned char FQBQData730[16] = {
2431                0x34,0x74,0xb4,
2432                0x23,0x63,0xa3,
2433                0x12,0x52,0x92,
2434                0x01,0x41,0x81,
2435                0x00,0x40,0x80,
2436                0xff
2437   };
2438   static const unsigned short colortharray[6] = {
2439                1, 1, 2, 2, 3, 4
2440   };
2441
2442   i = 0;
2443
2444   if(ModeNo > 0x13) {
2445
2446      /* Get VCLK  */
2447      if(SiS_Pr->UseCustomMode) {
2448         VCLK = SiS_Pr->CSRClock;
2449      } else {
2450         data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2451         VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
2452      }
2453
2454      /* Get MCLK * 16 */
2455      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
2456      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
2457
2458      /* Get half colordepth */
2459      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2460
2461      if(SiS_Pr->ChipType == SIS_730) {
2462         queuedata = &FQBQData730[0];
2463      } else {
2464         queuedata = &FQBQData[0];
2465      }
2466
2467      do {
2468         templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
2469
2470         datal = templ % MCLK16;
2471         templ = (templ / MCLK16) + 1;
2472         if(datal) templ++;
2473
2474         if(templ > 0x13) {
2475            if(queuedata[i + 1] == 0xFF) {
2476               ThresholdLow = 0x13;
2477               break;
2478            }
2479            i++;
2480         } else {
2481            ThresholdLow = templ;
2482            break;
2483         }
2484      } while(queuedata[i] != 0xFF);
2485
2486   } else {
2487
2488      if(SiS_Pr->ChipType != SIS_730) i = 9;
2489      ThresholdLow = 0x02;
2490
2491   }
2492
2493   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2494   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
2495   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
2496
2497   data = (ThresholdLow & 0x10) << 1;
2498   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
2499
2500   /* What is this? */
2501   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2502
2503   /* Write CRT/CPU threshold high (gap = 3) */
2504   data = ThresholdLow + 3;
2505   if(data > 0x0f) data = 0x0f;
2506   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
2507
2508  /* Write foreground and background queue */
2509#ifdef SIS_LINUX_KERNEL
2510   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
2511#else
2512   templ = pciReadLong(0x00000000, 0x50);
2513#endif
2514
2515   if(SiS_Pr->ChipType == SIS_730) {
2516
2517      templ &= 0xfffff9ff;
2518      templ |= ((queuedata[i] & 0xc0) << 3);
2519
2520   } else {
2521
2522      templ &= 0xf0ffffff;
2523      if( (ModeNo <= 0x13) &&
2524          (SiS_Pr->ChipType == SIS_630) &&
2525          (SiS_Pr->ChipRevision >= 0x30) ) {
2526         templ |= 0x0b000000;
2527      } else {
2528         templ |= ((queuedata[i] & 0xf0) << 20);
2529      }
2530
2531   }
2532
2533#ifdef SIS_LINUX_KERNEL
2534   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
2535   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
2536#else
2537   pciWriteLong(0x00000000, 0x50, templ);
2538   templ = pciReadLong(0x00000000, 0xA0);
2539#endif
2540
2541   /* GUI grant timer (PCI config 0xA3) */
2542   if(SiS_Pr->ChipType == SIS_730) {
2543
2544      templ &= 0x00ffffff;
2545      datal = queuedata[i] << 8;
2546      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
2547
2548   } else {
2549
2550      templ &= 0xf0ffffff;
2551      templ |= ((queuedata[i] & 0x0f) << 24);
2552
2553   }
2554
2555#ifdef SIS_LINUX_KERNEL
2556   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
2557#else
2558   pciWriteLong(0x00000000, 0xA0, templ);
2559#endif
2560}
2561#endif /* SIS300 */
2562
2563#ifdef SIS315H
2564static void
2565SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2566{
2567   unsigned short modeflag;
2568
2569   /* disable auto-threshold */
2570   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
2571
2572   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2573
2574   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
2575   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
2576   if(ModeNo > 0x13) {
2577      if(SiS_Pr->ChipType >= XGI_20) {
2578         SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2579         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2580      } else if(SiS_Pr->ChipType >= SIS_661) {
2581         if(!(modeflag & HalfDCLK)) {
2582            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2583            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2584         }
2585      } else {
2586         if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
2587            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2588            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2589         }
2590      }
2591   }
2592}
2593#endif
2594
2595/*********************************************/
2596/*              MODE REGISTERS               */
2597/*********************************************/
2598
2599static void
2600SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2601                unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
2602{
2603   unsigned short data = 0, VCLK = 0, index = 0;
2604
2605   if(ModeNo > 0x13) {
2606      if(SiS_Pr->UseCustomMode) {
2607         VCLK = SiS_Pr->CSRClock;
2608      } else {
2609         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2610         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2611      }
2612   }
2613
2614   if(SiS_Pr->ChipType < SIS_315H) {
2615#ifdef SIS300
2616      if(VCLK > 150) data |= 0x80;
2617      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
2618
2619      data = 0x00;
2620      if(VCLK >= 150) data |= 0x08;
2621      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
2622#endif
2623   } else if(SiS_Pr->ChipType < XGI_20) {
2624#ifdef SIS315H
2625      if(VCLK >= 166) data |= 0x0c;
2626      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2627
2628      if(VCLK >= 166) {
2629         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
2630      }
2631#endif
2632   } else {
2633#ifdef SIS315H
2634      if(VCLK >= 200) data |= 0x0c;
2635      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
2636      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2637      if(SiS_Pr->ChipType != XGI_20) {
2638         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
2639         if(VCLK < 200) data |= 0x10;
2640         SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
2641      }
2642#endif
2643   }
2644
2645   /* DAC speed */
2646   if(SiS_Pr->ChipType >= SIS_661) {
2647
2648      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
2649
2650   } else {
2651
2652      data = 0x03;
2653      if(VCLK >= 260)      data = 0x00;
2654      else if(VCLK >= 160) data = 0x01;
2655      else if(VCLK >= 135) data = 0x02;
2656
2657      if(SiS_Pr->ChipType == SIS_540) {
2658         if((VCLK == 203) || (VCLK < 234)) data = 0x02;
2659      }
2660
2661      if(SiS_Pr->ChipType < SIS_315H) {
2662         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
2663      } else {
2664         if(SiS_Pr->ChipType > SIS_315PRO) {
2665            if(ModeNo > 0x13) data &= 0xfc;
2666         }
2667         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
2668      }
2669
2670   }
2671}
2672
2673static void
2674SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2675                unsigned short ModeIdIndex, unsigned short RRTI)
2676{
2677   unsigned short data, infoflag = 0, modeflag, resindex;
2678#ifdef SIS315H
2679   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
2680   unsigned short data2, data3;
2681#endif
2682
2683   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2684
2685   if(SiS_Pr->UseCustomMode) {
2686      infoflag = SiS_Pr->CInfoFlag;
2687   } else {
2688      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
2689      if(ModeNo > 0x13) {
2690         infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2691      }
2692   }
2693
2694   /* Disable DPMS */
2695   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
2696
2697   data = 0;
2698   if(ModeNo > 0x13) {
2699      if(SiS_Pr->SiS_ModeType > ModeEGA) {
2700         data |= 0x02;
2701         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
2702      }
2703      if(infoflag & InterlaceMode) data |= 0x20;
2704   }
2705   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
2706
2707   if(SiS_Pr->ChipType != SIS_300) {
2708      data = 0;
2709      if(infoflag & InterlaceMode) {
2710         /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
2711         int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
2712                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
2713         int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
2714                    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
2715         data = hrs - (hto >> 1) + 3;
2716      }
2717      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
2718      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
2719   }
2720
2721   if(modeflag & HalfDCLK) {
2722      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
2723   }
2724
2725   data = 0;
2726   if(modeflag & LineCompareOff) data = 0x08;
2727   if(SiS_Pr->ChipType == SIS_300) {
2728      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
2729   } else {
2730      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
2731      if(SiS_Pr->SiS_ModeType == ModeEGA) {
2732         if(ModeNo > 0x13) {
2733            data |= 0x40;
2734         }
2735      }
2736      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
2737   }
2738
2739#ifdef SIS315H
2740   if(SiS_Pr->ChipType >= SIS_315H) {
2741      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
2742   }
2743
2744   if(SiS_Pr->ChipType == SIS_315PRO) {
2745
2746      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
2747      if(SiS_Pr->SiS_ModeType == ModeText) {
2748         data &= 0xc7;
2749      } else {
2750         data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
2751         if(infoflag & InterlaceMode) data2 >>= 1;
2752         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2753         if(data3) data2 /= data3;
2754         if(data2 >= 0x50) {
2755            data &= 0x0f;
2756            data |= 0x50;
2757         }
2758      }
2759      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2760
2761   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
2762
2763      data = SiS_Get310DRAMType(SiS_Pr);
2764      if(SiS_Pr->ChipType == SIS_330) {
2765         data = SiS_Pr->SiS_SR15[(2 * 4) + data];
2766      } else {
2767         if(SiS_Pr->SiS_ROMNew)      data = ROMAddr[0xf6];
2768         else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
2769         else                        data = 0xba;
2770      }
2771      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
2772         data &= 0xc7;
2773      } else {
2774         if(SiS_Pr->UseCustomMode) {
2775            data2 = SiS_Pr->CSRClock;
2776         } else {
2777            data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2778            data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
2779         }
2780
2781         data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2782         if(data3) data2 *= data3;
2783
2784         data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
2785
2786         if(SiS_Pr->ChipType == SIS_330) {
2787            if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
2788               if     (data2 >= 0x19c) data = 0xba;
2789               else if(data2 >= 0x140) data = 0x7a;
2790               else if(data2 >= 0x101) data = 0x3a;
2791               else if(data2 >= 0xf5)  data = 0x32;
2792               else if(data2 >= 0xe2)  data = 0x2a;
2793               else if(data2 >= 0xc4)  data = 0x22;
2794               else if(data2 >= 0xac)  data = 0x1a;
2795               else if(data2 >= 0x9e)  data = 0x12;
2796               else if(data2 >= 0x8e)  data = 0x0a;
2797               else                    data = 0x02;
2798            } else {
2799               if(data2 >= 0x127)      data = 0xba;
2800               else                    data = 0x7a;
2801            }
2802         } else {  /* 76x+LFB */
2803            if     (data2 >= 0x190) data = 0xba;
2804            else if(data2 >= 0xff)  data = 0x7a;
2805            else if(data2 >= 0xd3)  data = 0x3a;
2806            else if(data2 >= 0xa9)  data = 0x1a;
2807            else if(data2 >= 0x93)  data = 0x0a;
2808            else                    data = 0x02;
2809         }
2810      }
2811      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2812
2813   }
2814      /* XGI: Nothing. */
2815      /* TODO: Check SiS340 */
2816#endif
2817
2818   data = 0x60;
2819   if(SiS_Pr->SiS_ModeType != ModeText) {
2820      data ^= 0x60;
2821      if(SiS_Pr->SiS_ModeType != ModeEGA) {
2822         data ^= 0xA0;
2823      }
2824   }
2825   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
2826
2827   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
2828
2829#ifdef SIS315H
2830   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
2831       (SiS_Pr->ChipType == XGI_40)) {
2832      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2833         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
2834      } else {
2835         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
2836      }
2837   } else if(SiS_Pr->ChipType == XGI_20) {
2838      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2839         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
2840      } else {
2841         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
2842      }
2843      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
2844   }
2845#endif
2846}
2847
2848#ifdef SIS315H
2849static void
2850SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
2851{
2852#if 0
2853   /* TODO: Find out about IOAddress2 */
2854   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
2855   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
2856   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
2857   int i;
2858
2859   if((SiS_Pr->ChipRevision != 0) ||
2860      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
2861      return;
2862
2863   for(i = 0; i <= 4; i++) {                                    /* SR00 - SR04 */
2864      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
2865   }
2866   for(i = 0; i <= 8; i++) {                                    /* GR00 - GR08 */
2867      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
2868   }
2869   SiS_SetReg(P2_3c4,0x05,0x86);
2870   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));   /* SR06 */
2871   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));   /* SR21 */
2872   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));     /* MISC */
2873   SiS_SetReg(P2_3c4,0x05,0x00);
2874#endif
2875}
2876#endif
2877
2878/*********************************************/
2879/*                 LOAD DAC                  */
2880/*********************************************/
2881
2882static void
2883SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
2884             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
2885{
2886   unsigned short d1, d2, d3;
2887
2888   switch(dl) {
2889   case  0: d1 = dh; d2 = ah; d3 = al; break;
2890   case  1: d1 = ah; d2 = al; d3 = dh; break;
2891   default: d1 = al; d2 = dh; d3 = ah;
2892   }
2893   SiS_SetRegByte(DACData, (d1 << shiftflag));
2894   SiS_SetRegByte(DACData, (d2 << shiftflag));
2895   SiS_SetRegByte(DACData, (d3 << shiftflag));
2896}
2897
2898void
2899SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2900{
2901   unsigned short data, data2, time, i, j, k, m, n, o;
2902   unsigned short si, di, bx, sf;
2903   SISIOADDRESS DACAddr, DACData;
2904   const unsigned char *table = NULL;
2905
2906   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
2907
2908   j = time = 64;
2909   if(data == 0x00)      table = SiS_MDA_DAC;
2910   else if(data == 0x08) table = SiS_CGA_DAC;
2911   else if(data == 0x10) table = SiS_EGA_DAC;
2912   else if(data == 0x18) {
2913      j = 16;
2914      time = 256;
2915      table = SiS_VGA_DAC;
2916   }
2917
2918   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
2919         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
2920       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
2921       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
2922      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
2923      DACAddr = SiS_Pr->SiS_P3c8;
2924      DACData = SiS_Pr->SiS_P3c9;
2925      sf = 0;
2926   } else {
2927      DACAddr = SiS_Pr->SiS_Part5Port;
2928      DACData = SiS_Pr->SiS_Part5Port + 1;
2929      sf = 2;
2930   }
2931
2932   SiS_SetRegByte(DACAddr,0x00);
2933
2934   for(i = 0; i < j; i++) {
2935      data = table[i];
2936      for(k = 0; k < 3; k++) {
2937        data2 = 0;
2938        if(data & 0x01) data2 += 0x2A;
2939        if(data & 0x02) data2 += 0x15;
2940        SiS_SetRegByte(DACData, (data2 << sf));
2941        data >>= 2;
2942      }
2943   }
2944
2945   if(time == 256) {
2946      for(i = 16; i < 32; i++) {
2947         data = table[i] << sf;
2948         for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
2949      }
2950      si = 32;
2951      for(m = 0; m < 9; m++) {
2952         di = si;
2953         bx = si + 4;
2954         for(n = 0; n < 3; n++) {
2955            for(o = 0; o < 5; o++) {
2956               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
2957               si++;
2958            }
2959            si -= 2;
2960            for(o = 0; o < 3; o++) {
2961               SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
2962               si--;
2963            }
2964         }            /* for n < 3 */
2965         si += 5;
2966      }               /* for m < 9 */
2967   }
2968}
2969
2970/*********************************************/
2971/*         SET CRT1 REGISTER GROUP           */
2972/*********************************************/
2973
2974static void
2975SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2976{
2977   unsigned short StandTableIndex, RefreshRateTableIndex;
2978
2979   SiS_Pr->SiS_CRT1Mode = ModeNo;
2980
2981   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
2982
2983   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
2984      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
2985         SiS_DisableBridge(SiS_Pr);
2986      }
2987   }
2988
2989   SiS_ResetSegmentRegisters(SiS_Pr);
2990
2991   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
2992   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
2993   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
2994   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
2995   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
2996   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
2997   SiS_ResetCRT1VCLK(SiS_Pr);
2998
2999   SiS_Pr->SiS_SelectCRT2Rate = 0;
3000   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
3001
3002#ifdef SIS_XORG_XF86
3003   xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
3004                    SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
3005#endif
3006
3007   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
3008      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3009         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
3010      }
3011   }
3012
3013   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3014      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
3015   }
3016
3017   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
3018
3019   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3020      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
3021   }
3022
3023   if(RefreshRateTableIndex != 0xFFFF) {
3024      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
3025      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3026      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3027      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3028   }
3029
3030   switch(SiS_Pr->ChipType) {
3031#ifdef SIS300
3032   case SIS_300:
3033      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
3034      break;
3035   case SIS_540:
3036   case SIS_630:
3037   case SIS_730:
3038      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
3039      break;
3040#endif
3041   default:
3042#ifdef SIS315H
3043      if(SiS_Pr->ChipType == XGI_20) {
3044         unsigned char sr2b = 0, sr2c = 0;
3045         switch(ModeNo) {
3046         case 0x00:
3047         case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
3048         case 0x04:
3049         case 0x05:
3050         case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
3051         }
3052         if(sr2b) {
3053            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
3054            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
3055            SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
3056         }
3057      }
3058      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
3059#endif
3060      break;
3061   }
3062
3063   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3064
3065#ifdef SIS315H
3066   if(SiS_Pr->ChipType == XGI_40) {
3067      SiS_SetupDualChip(SiS_Pr);
3068   }
3069#endif
3070
3071   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
3072
3073#ifdef SIS_LINUX_KERNEL
3074   if(SiS_Pr->SiS_flag_clearbuffer) {
3075      SiS_ClearBuffer(SiS_Pr, ModeNo);
3076   }
3077#endif
3078
3079   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
3080      SiS_WaitRetrace1(SiS_Pr);
3081      SiS_DisplayOn(SiS_Pr);
3082   }
3083}
3084
3085/*********************************************/
3086/*       HELPER: VIDEO BRIDGE PROG CLK       */
3087/*********************************************/
3088
3089static void
3090SiS_InitVB(struct SiS_Private *SiS_Pr)
3091{
3092   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3093
3094   SiS_Pr->Init_P4_0E = 0;
3095   if(SiS_Pr->SiS_ROMNew) {
3096      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
3097   } else if(SiS_Pr->ChipType >= XGI_40) {
3098      if(SiS_Pr->SiS_XGIROM) {
3099         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
3100      }
3101   }
3102}
3103
3104static void
3105SiS_ResetVB(struct SiS_Private *SiS_Pr)
3106{
3107#ifdef SIS315H
3108   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
3109   unsigned short temp;
3110
3111   /* VB programming clock */
3112   if(SiS_Pr->SiS_UseROM) {
3113      if(SiS_Pr->ChipType < SIS_330) {
3114         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
3115         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3116         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3117      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
3118         temp = ROMAddr[0x7e] | 0x40;
3119         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3120         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3121      }
3122   } else if(SiS_Pr->ChipType >= XGI_40) {
3123      temp = 0x40;
3124      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
3125      /* Can we do this on any chipset? */
3126      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3127   }
3128#endif
3129}
3130
3131/*********************************************/
3132/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
3133/*********************************************/
3134
3135static void
3136SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3137{
3138   /* SiS65x and XGI set up some sort of "lock mode" for text
3139    * which locks CRT2 in some way to CRT1 timing. Disable
3140    * this here.
3141    */
3142#ifdef SIS315H
3143   if((IS_SIS651) || (IS_SISM650) ||
3144      SiS_Pr->ChipType == SIS_340 ||
3145      SiS_Pr->ChipType == XGI_40) {
3146      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
3147      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
3148      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
3149      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
3150      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
3151   }
3152   /* !!! This does not support modes < 0x13 !!! */
3153#endif
3154}
3155
3156/*********************************************/
3157/*     HELPER: SET AGP TIMING FOR SiS760     */
3158/*********************************************/
3159
3160static void
3161SiS_Handle760(struct SiS_Private *SiS_Pr)
3162{
3163#ifdef SIS315H
3164   unsigned int somebase;
3165   unsigned char temp1, temp2, temp3;
3166
3167   if( (SiS_Pr->ChipType != SIS_760)                         ||
3168       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
3169       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
3170       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
3171      return;
3172
3173#ifdef SIS_LINUX_KERNEL
3174   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
3175#else
3176   somebase = pciReadWord(0x00001000, 0x74);
3177#endif
3178   somebase &= 0xffff;
3179
3180   if(somebase == 0) return;
3181
3182   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
3183
3184   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
3185      temp1 = 0x21;
3186      temp2 = 0x03;
3187      temp3 |= 0x08;
3188   } else {
3189      temp1 = 0x25;
3190      temp2 = 0x0b;
3191   }
3192
3193#ifdef SIS_LINUX_KERNEL
3194   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
3195   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
3196#else
3197   pciWriteByte(0x00000000, 0x7e, temp1);
3198   pciWriteByte(0x00000000, 0x8d, temp2);
3199#endif
3200
3201   SiS_SetRegByte((somebase + 0x85), temp3);
3202#endif
3203}
3204
3205/*********************************************/
3206/*      X.org/XFree86: SET SCREEN PITCH      */
3207/*********************************************/
3208
3209#ifdef SIS_XORG_XF86
3210static void
3211SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3212{
3213   SISPtr pSiS = SISPTR(pScrn);
3214   unsigned short HDisplay = pSiS->scrnPitch >> 3;
3215
3216   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
3217   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
3218}
3219
3220static void
3221SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3222{
3223   SISPtr pSiS = SISPTR(pScrn);
3224   unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
3225
3226    /* Unlock CRT2 */
3227   if(pSiS->VGAEngine == SIS_315_VGA)
3228      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
3229   else
3230      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
3231
3232   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
3233   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
3234}
3235
3236static void
3237SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3238{
3239   SISPtr pSiS = SISPTR(pScrn);
3240   bool isslavemode = false;
3241
3242   if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
3243       ( ((pSiS->VGAEngine == SIS_300_VGA) &&
3244          (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
3245         ((pSiS->VGAEngine == SIS_315_VGA) &&
3246          (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
3247      isslavemode = true;
3248   }
3249
3250   /* We need to set pitch for CRT1 if bridge is in slave mode, too */
3251   if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) {
3252      SiS_SetPitchCRT1(SiS_Pr, pScrn);
3253   }
3254   /* We must not set the pitch for CRT2 if bridge is in slave mode */
3255   if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) {
3256      SiS_SetPitchCRT2(SiS_Pr, pScrn);
3257   }
3258}
3259#endif
3260
3261/*********************************************/
3262/*                 SiSSetMode()              */
3263/*********************************************/
3264
3265#ifdef SIS_XORG_XF86
3266/* We need pScrn for setting the pitch correctly */
3267bool
3268SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, bool dosetpitch)
3269#else
3270bool
3271SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3272#endif
3273{
3274   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3275   unsigned short RealModeNo, ModeIdIndex;
3276   unsigned char  backupreg = 0;
3277#ifdef SIS_LINUX_KERNEL
3278   unsigned short KeepLockReg;
3279
3280   SiS_Pr->UseCustomMode = false;
3281   SiS_Pr->CRT1UsesCustomMode = false;
3282#endif
3283
3284   SiS_Pr->SiS_flag_clearbuffer = 0;
3285
3286   if(SiS_Pr->UseCustomMode) {
3287      ModeNo = 0xfe;
3288   } else {
3289#ifdef SIS_LINUX_KERNEL
3290      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
3291#endif
3292      ModeNo &= 0x7f;
3293   }
3294
3295   /* Don't use FSTN mode for CRT1 */
3296   RealModeNo = ModeNo;
3297   if(ModeNo == 0x5b) ModeNo = 0x56;
3298
3299   SiSInitPtr(SiS_Pr);
3300   SiSRegInit(SiS_Pr, BaseAddr);
3301   SiS_GetSysFlags(SiS_Pr);
3302
3303   SiS_Pr->SiS_VGAINFO = 0x11;
3304#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
3305   if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3306#endif
3307
3308#ifdef SIS_LINUX_KERNEL
3309   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
3310#endif
3311   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3312
3313   SiSInitPCIetc(SiS_Pr);
3314   SiSSetLVDSetc(SiS_Pr);
3315   SiSDetermineROMUsage(SiS_Pr);
3316
3317   SiS_UnLockCRT2(SiS_Pr);
3318
3319   if(!SiS_Pr->UseCustomMode) {
3320      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3321   } else {
3322      ModeIdIndex = 0;
3323   }
3324
3325   SiS_GetVBType(SiS_Pr);
3326
3327   /* Init/restore some VB registers */
3328   SiS_InitVB(SiS_Pr);
3329   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3330      if(SiS_Pr->ChipType >= SIS_315H) {
3331         SiS_ResetVB(SiS_Pr);
3332         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3333         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3334         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3335      } else {
3336         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3337      }
3338   }
3339
3340   /* Get VB information (connectors, connected devices) */
3341   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
3342   SiS_SetYPbPr(SiS_Pr);
3343   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3344   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3345   SiS_SetLowModeTest(SiS_Pr, ModeNo);
3346
3347#ifdef SIS_LINUX_KERNEL
3348   /* Check memory size (kernel framebuffer driver only) */
3349   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
3350      return false;
3351   }
3352#endif
3353
3354   SiS_OpenCRTC(SiS_Pr);
3355
3356   if(SiS_Pr->UseCustomMode) {
3357      SiS_Pr->CRT1UsesCustomMode = true;
3358      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3359      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3360   } else {
3361      SiS_Pr->CRT1UsesCustomMode = false;
3362   }
3363
3364   /* Set mode on CRT1 */
3365   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
3366       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
3367      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3368   }
3369
3370   /* Set mode on CRT2 */
3371   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
3372      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
3373          (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
3374          (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
3375          (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3376         SiS_SetCRT2Group(SiS_Pr, RealModeNo);
3377      }
3378   }
3379
3380   SiS_HandleCRT1(SiS_Pr);
3381
3382   SiS_StrangeStuff(SiS_Pr);
3383
3384   SiS_DisplayOn(SiS_Pr);
3385   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3386
3387#ifdef SIS315H
3388   if(SiS_Pr->ChipType >= SIS_315H) {
3389      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3390         if(!(SiS_IsDualEdge(SiS_Pr))) {
3391            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3392         }
3393      }
3394   }
3395#endif
3396
3397   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3398      if(SiS_Pr->ChipType >= SIS_315H) {
3399#ifdef SIS315H
3400         if(!SiS_Pr->SiS_ROMNew) {
3401            if(SiS_IsVAMode(SiS_Pr)) {
3402               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3403            } else {
3404               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3405            }
3406         }
3407
3408         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3409
3410         if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
3411            if((ModeNo == 0x03) || (ModeNo == 0x10)) {
3412               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
3413               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
3414            }
3415         }
3416
3417         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3418            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3419         }
3420#endif
3421      } else if((SiS_Pr->ChipType == SIS_630) ||
3422                (SiS_Pr->ChipType == SIS_730)) {
3423         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3424      }
3425   }
3426
3427#ifdef SIS_XORG_XF86
3428   if(pScrn) {
3429      /* SetPitch: Adapt to virtual size & position */
3430      if((ModeNo > 0x13) && (dosetpitch)) {
3431         SiS_SetPitch(SiS_Pr, pScrn);
3432      }
3433
3434      /* Backup/Set ModeNo in BIOS scratch area */
3435      SiS_GetSetModeID(pScrn, ModeNo);
3436   }
3437#endif
3438
3439   SiS_CloseCRTC(SiS_Pr);
3440
3441   SiS_Handle760(SiS_Pr);
3442
3443#ifdef SIS_LINUX_KERNEL
3444   /* We never lock registers in XF86 */
3445   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
3446#endif
3447
3448   return true;
3449}
3450
3451/*********************************************/
3452/*       X.org/XFree86: SiSBIOSSetMode()     */
3453/*           for non-Dual-Head mode          */
3454/*********************************************/
3455
3456#ifdef SIS_XORG_XF86
3457bool
3458SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3459               DisplayModePtr mode, bool IsCustom)
3460{
3461   SISPtr pSiS = SISPTR(pScrn);
3462   unsigned short ModeNo = 0;
3463
3464   SiS_Pr->UseCustomMode = false;
3465
3466   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3467
3468      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
3469                SiS_Pr->CHDisplay,
3470                (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
3471                   (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
3472                      SiS_Pr->CVDisplay)));
3473
3474   } else {
3475
3476      /* Don't need vbflags here; checks done earlier */
3477      ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
3478      if(!ModeNo) return false;
3479
3480      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
3481
3482   }
3483
3484   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, true));
3485}
3486
3487/*********************************************/
3488/*    X.org/XFree86: SiSBIOSSetModeCRT2()    */
3489/*           for Dual-Head modes             */
3490/*********************************************/
3491
3492bool
3493SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3494               DisplayModePtr mode, bool IsCustom)
3495{
3496   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3497   SISPtr  pSiS = SISPTR(pScrn);
3498#ifdef SISDUALHEAD
3499   SISEntPtr pSiSEnt = pSiS->entityPrivate;
3500#endif
3501   unsigned short ModeIdIndex;
3502   unsigned short ModeNo = 0;
3503   unsigned char  backupreg = 0;
3504
3505   SiS_Pr->UseCustomMode = false;
3506
3507   /* Remember: Custom modes for CRT2 are ONLY supported
3508    *     -) on the 30x/B/C, and
3509    *     -) if CRT2 is LCD or VGA, or CRT1 is LCDA
3510    */
3511
3512   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3513
3514         ModeNo = 0xfe;
3515
3516   } else {
3517
3518         ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
3519         if(!ModeNo) return false;
3520
3521   }
3522
3523   SiSRegInit(SiS_Pr, BaseAddr);
3524   SiSInitPtr(SiS_Pr);
3525   SiS_GetSysFlags(SiS_Pr);
3526#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
3527   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3528#else
3529   SiS_Pr->SiS_VGAINFO = 0x11;
3530#endif
3531
3532   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3533
3534   SiSInitPCIetc(SiS_Pr);
3535   SiSSetLVDSetc(SiS_Pr);
3536   SiSDetermineROMUsage(SiS_Pr);
3537
3538   /* Save mode info so we can set it from within SetMode for CRT1 */
3539#ifdef SISDUALHEAD
3540   if(pSiS->DualHeadMode) {
3541      pSiSEnt->CRT2ModeNo = ModeNo;
3542      pSiSEnt->CRT2DMode = mode;
3543      pSiSEnt->CRT2IsCustom = IsCustom;
3544      pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
3545      pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
3546      pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3547      pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3548#if 0
3549      /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
3550      if(pSiSEnt->CRT1ModeNo == -1) {
3551         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3552                "Setting CRT2 mode delayed until after setting CRT1 mode\n");
3553         return true;
3554      }
3555#endif
3556      pSiSEnt->CRT2ModeSet = true;
3557   }
3558#endif
3559
3560   if(SiS_Pr->UseCustomMode) {
3561
3562      unsigned short temptemp = SiS_Pr->CVDisplay;
3563
3564      if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
3565      else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
3566
3567      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3568          "Setting custom mode %dx%d on CRT2\n",
3569          SiS_Pr->CHDisplay, temptemp);
3570
3571   } else {
3572
3573      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3574          "Setting standard mode 0x%x on CRT2\n", ModeNo);
3575
3576   }
3577
3578   SiS_UnLockCRT2(SiS_Pr);
3579
3580   if(!SiS_Pr->UseCustomMode) {
3581      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3582   } else {
3583      ModeIdIndex = 0;
3584   }
3585
3586   SiS_GetVBType(SiS_Pr);
3587
3588   SiS_InitVB(SiS_Pr);
3589   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3590      if(SiS_Pr->ChipType >= SIS_315H) {
3591         SiS_ResetVB(SiS_Pr);
3592         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3593         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3594         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3595      } else {
3596         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3597      }
3598   }
3599
3600   /* Get VB information (connectors, connected devices) */
3601   if(!SiS_Pr->UseCustomMode) {
3602      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
3603   } else {
3604      /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
3605      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
3606   }
3607   SiS_SetYPbPr(SiS_Pr);
3608   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3609   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3610   SiS_SetLowModeTest(SiS_Pr, ModeNo);
3611
3612   SiS_ResetSegmentRegisters(SiS_Pr);
3613
3614   /* Set mode on CRT2 */
3615   if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
3616       (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
3617       (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
3618       (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3619      SiS_SetCRT2Group(SiS_Pr, ModeNo);
3620   }
3621
3622   SiS_StrangeStuff(SiS_Pr);
3623
3624   SiS_DisplayOn(SiS_Pr);
3625   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3626
3627   if(SiS_Pr->ChipType >= SIS_315H) {
3628      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3629         if(!(SiS_IsDualEdge(SiS_Pr))) {
3630            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3631         }
3632      }
3633   }
3634
3635   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3636      if(SiS_Pr->ChipType >= SIS_315H) {
3637         if(!SiS_Pr->SiS_ROMNew) {
3638            if(SiS_IsVAMode(SiS_Pr)) {
3639               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3640            } else {
3641               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3642            }
3643         }
3644
3645         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3646
3647         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3648            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3649         }
3650      } else if((SiS_Pr->ChipType == SIS_630) ||
3651                (SiS_Pr->ChipType == SIS_730)) {
3652         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3653      }
3654   }
3655
3656   /* SetPitch: Adapt to virtual size & position */
3657   SiS_SetPitchCRT2(SiS_Pr, pScrn);
3658
3659   SiS_Handle760(SiS_Pr);
3660
3661   return true;
3662}
3663
3664/*********************************************/
3665/*    X.org/XFree86: SiSBIOSSetModeCRT1()    */
3666/*           for Dual-Head modes             */
3667/*********************************************/
3668
3669bool
3670SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3671                   DisplayModePtr mode, bool IsCustom)
3672{
3673   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3674   SISPtr  pSiS = SISPTR(pScrn);
3675   unsigned short ModeIdIndex, ModeNo = 0;
3676   unsigned char  backupreg = 0;
3677#ifdef SISDUALHEAD
3678   SISEntPtr pSiSEnt = pSiS->entityPrivate;
3679   unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
3680   bool backupcustom;
3681#endif
3682
3683   SiS_Pr->UseCustomMode = false;
3684
3685   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3686
3687         unsigned short temptemp = SiS_Pr->CVDisplay;
3688
3689         if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
3690         else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
3691
3692         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3693                "Setting custom mode %dx%d on CRT1\n",
3694                SiS_Pr->CHDisplay, temptemp);
3695         ModeNo = 0xfe;
3696
3697   } else {
3698
3699         ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
3700         if(!ModeNo) return false;
3701
3702         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3703                "Setting standard mode 0x%x on CRT1\n", ModeNo);
3704   }
3705
3706   SiSInitPtr(SiS_Pr);
3707   SiSRegInit(SiS_Pr, BaseAddr);
3708   SiS_GetSysFlags(SiS_Pr);
3709#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
3710   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3711#else
3712   SiS_Pr->SiS_VGAINFO = 0x11;
3713#endif
3714
3715   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3716
3717   SiSInitPCIetc(SiS_Pr);
3718   SiSSetLVDSetc(SiS_Pr);
3719   SiSDetermineROMUsage(SiS_Pr);
3720
3721   SiS_UnLockCRT2(SiS_Pr);
3722
3723   if(!SiS_Pr->UseCustomMode) {
3724      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3725   } else {
3726      ModeIdIndex = 0;
3727   }
3728
3729   /* Determine VBType */
3730   SiS_GetVBType(SiS_Pr);
3731
3732   SiS_InitVB(SiS_Pr);
3733   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3734      if(SiS_Pr->ChipType >= SIS_315H) {
3735         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3736      } else {
3737         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3738      }
3739   }
3740
3741   /* Get VB information (connectors, connected devices) */
3742   /* (We don't care if the current mode is a CRT2 mode) */
3743   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
3744   SiS_SetYPbPr(SiS_Pr);
3745   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3746   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3747   SiS_SetLowModeTest(SiS_Pr, ModeNo);
3748
3749   SiS_OpenCRTC(SiS_Pr);
3750
3751   /* Set mode on CRT1 */
3752   SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3753   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3754      SiS_SetCRT2Group(SiS_Pr, ModeNo);
3755   }
3756
3757   /* SetPitch: Adapt to virtual size & position */
3758   SiS_SetPitchCRT1(SiS_Pr, pScrn);
3759
3760   SiS_HandleCRT1(SiS_Pr);
3761
3762   SiS_StrangeStuff(SiS_Pr);
3763
3764   SiS_CloseCRTC(SiS_Pr);
3765
3766#ifdef SISDUALHEAD
3767   if(pSiS->DualHeadMode) {
3768      pSiSEnt->CRT1ModeNo = ModeNo;
3769      pSiSEnt->CRT1DMode = mode;
3770   }
3771#endif
3772
3773   if(SiS_Pr->UseCustomMode) {
3774      SiS_Pr->CRT1UsesCustomMode = true;
3775      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3776      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3777   } else {
3778      SiS_Pr->CRT1UsesCustomMode = false;
3779   }
3780
3781   /* Reset CRT2 if changing mode on CRT1 */
3782#ifdef SISDUALHEAD
3783   if(pSiS->DualHeadMode) {
3784      if(pSiSEnt->CRT2ModeNo != -1) {
3785         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3786                                "(Re-)Setting mode for CRT2\n");
3787         backupcustom = SiS_Pr->UseCustomMode;
3788         backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
3789         backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
3790         backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3791         backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3792         if(SiS_Pr->SiS_VBType & VB_SISVB) {
3793            /* Backup LUT-enable */
3794            if(pSiSEnt->CRT2ModeSet) {
3795               backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08;
3796            }
3797         }
3798         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3799            SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30);
3800            SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31);
3801            SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
3802            SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
3803         }
3804
3805         SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
3806                            pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
3807
3808         SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
3809         SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
3810         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
3811         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
3812         if(SiS_Pr->SiS_VBType & VB_SISVB) {
3813            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d);
3814         }
3815         SiS_Pr->UseCustomMode = backupcustom;
3816      }
3817   }
3818#endif
3819
3820   /* Warning: From here, the custom mode entries in SiS_Pr are
3821    * possibly overwritten
3822    */
3823
3824   SiS_DisplayOn(SiS_Pr);
3825   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3826
3827   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3828      if(SiS_Pr->ChipType >= SIS_315H) {
3829         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3830      } else if((SiS_Pr->ChipType == SIS_630) ||
3831                (SiS_Pr->ChipType == SIS_730)) {
3832         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3833      }
3834   }
3835
3836   SiS_Handle760(SiS_Pr);
3837
3838   /* Backup/Set ModeNo in BIOS scratch area */
3839   SiS_GetSetModeID(pScrn,ModeNo);
3840
3841   return true;
3842}
3843#endif /* Linux_XF86 */
3844
3845#ifndef GETBITSTR
3846#define BITMASK(h,l)            (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
3847#define GENMASK(mask)           BITMASK(1?mask,0?mask)
3848#define GETBITS(var,mask)       (((var) & GENMASK(mask)) >> (0?mask))
3849#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
3850#endif
3851
3852void
3853SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
3854{
3855   int x = 1; /* Fix sync */
3856
3857   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;                /* CR0 */
3858   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;                       /* CR1 */
3859   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;                    /* CR2 */
3860   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;    /* CR3 */
3861   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;                     /* CR4 */
3862   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |   /* CR5 */
3863                            (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
3864
3865   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;                 /* CR6 */
3866   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)          /* CR7 */
3867                          | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
3868                          | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
3869                          | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
3870                          | 0x10
3871                          | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
3872                          | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
3873                          | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
3874
3875   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5);  /* CR9 */
3876
3877   if(depth != 8) {
3878      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;         /* SRE */
3879      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
3880   }
3881
3882   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;                   /* CR10 */
3883   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;           /* CR11 */
3884   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;                   /* CR12 */
3885   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;                   /* CR15 */
3886   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;                   /* CR16 */
3887
3888   SiS_Pr->CCRT1CRTC[13] =                                                      /* SRA */
3889                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
3890                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
3891                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
3892                        GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
3893                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
3894                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
3895
3896   SiS_Pr->CCRT1CRTC[14] =                                                      /* SRB */
3897                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
3898                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
3899                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
3900                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
3901
3902
3903   SiS_Pr->CCRT1CRTC[15] =                                                      /* SRC */
3904                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
3905                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
3906}
3907
3908void
3909SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3910                unsigned short ModeIdIndex)
3911{
3912   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
3913   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
3914   int i, j;
3915
3916   /* 1:1 data: use data set by setcrt1crtc() */
3917   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
3918
3919   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
3920
3921   if(modeflag & HalfDCLK) VGAHDE >>= 1;
3922
3923   SiS_Pr->CHDisplay = VGAHDE;
3924   SiS_Pr->CHBlankStart = VGAHDE;
3925
3926   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
3927   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
3928
3929   if(SiS_Pr->ChipType < SIS_315H) {
3930#ifdef SIS300
3931      tempbx = SiS_Pr->SiS_VGAHT;
3932      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3933         tempbx = SiS_Pr->PanelHT;
3934      }
3935      if(modeflag & HalfDCLK) tempbx >>= 1;
3936      remaining = tempbx % 8;
3937#endif
3938   } else {
3939#ifdef SIS315H
3940      /* OK for LCDA, LVDS */
3941      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
3942      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
3943      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3944         tempax = SiS_Pr->PanelXRes;
3945      }
3946      tempbx += tempax;
3947      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
3948#endif
3949   }
3950   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
3951
3952   if(SiS_Pr->ChipType < SIS_315H) {
3953#ifdef SIS300
3954      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
3955         SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
3956         SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
3957         if(modeflag & HalfDCLK) {
3958            SiS_Pr->CHSyncStart >>= 1;
3959            SiS_Pr->CHSyncEnd >>= 1;
3960         }
3961      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3962         tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
3963         tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
3964         if(modeflag & HalfDCLK) {
3965            tempax >>= 1;
3966            tempbx >>= 1;
3967         }
3968         SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
3969         tempax = SiS_Pr->PanelHRE + 7;
3970         if(modeflag & HalfDCLK) tempax >>= 1;
3971         SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
3972      } else {
3973         SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
3974         if(modeflag & HalfDCLK) {
3975            SiS_Pr->CHSyncStart >>= 1;
3976            tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
3977            SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
3978         } else {
3979            SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
3980            SiS_Pr->CHSyncStart += 8;
3981         }
3982      }
3983#endif
3984   } else {
3985#ifdef SIS315H
3986      tempax = VGAHDE;
3987      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3988         tempbx = SiS_Pr->PanelXRes;
3989         if(modeflag & HalfDCLK) tempbx >>= 1;
3990         tempax += ((tempbx - tempax) >> 1);
3991      }
3992      tempax += SiS_Pr->PanelHRS;
3993      SiS_Pr->CHSyncStart = tempax;
3994      tempax += SiS_Pr->PanelHRE;
3995      SiS_Pr->CHSyncEnd = tempax;
3996#endif
3997   }
3998
3999   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
4000   tempax = SiS_Pr->SiS_VGAVDE;
4001   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
4002      tempax = SiS_Pr->PanelYRes;
4003   } else if(SiS_Pr->ChipType < SIS_315H) {
4004#ifdef SIS300
4005      /* Stupid hack for 640x400/320x200 */
4006      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
4007         if((tempax + tempbx) == 438) tempbx += 16;
4008      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
4009                (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
4010         tempax = 0;
4011         tempbx = SiS_Pr->SiS_VGAVT;
4012      }
4013#endif
4014   }
4015   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
4016
4017   tempax = SiS_Pr->SiS_VGAVDE;
4018   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
4019      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
4020   }
4021   tempax += SiS_Pr->PanelVRS;
4022   SiS_Pr->CVSyncStart = tempax;
4023   tempax += SiS_Pr->PanelVRE;
4024   SiS_Pr->CVSyncEnd = tempax;
4025   if(SiS_Pr->ChipType < SIS_315H) {
4026      SiS_Pr->CVSyncStart--;
4027      SiS_Pr->CVSyncEnd--;
4028   }
4029
4030   SiS_CalcCRRegisters(SiS_Pr, 8);
4031   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
4032   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
4033   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
4034
4035   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
4036
4037   for(i = 0, j = 0; i <= 7; i++, j++) {
4038      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
4039   }
4040   for(j = 0x10; i <= 10; i++, j++) {
4041      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
4042   }
4043   for(j = 0x15; i <= 12; i++, j++) {
4044      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
4045   }
4046   for(j = 0x0A; i <= 15; i++, j++) {
4047      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
4048   }
4049
4050   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
4051   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
4052
4053   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
4054   if(modeflag & DoubleScanMode) tempax |= 0x80;
4055   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
4056
4057#ifdef SIS_XORG_XF86
4058#ifdef TWDEBUG
4059   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
4060        SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
4061        SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
4062        SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
4063   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
4064        SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
4065        SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
4066        SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
4067        SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
4068   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
4069        SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
4070        SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
4071        SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
4072        SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
4073   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
4074#endif
4075#endif
4076}
4077
4078void
4079SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
4080                        int xres, int yres,
4081#ifdef SIS_XORG_XF86
4082                        DisplayModePtr current
4083#endif
4084#ifdef SIS_LINUX_KERNEL
4085                        struct fb_var_screeninfo *var, bool writeres
4086#endif
4087)
4088{
4089   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
4090   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
4091   unsigned char  sr_data, cr_data, cr_data2;
4092   int            A, B, C, D, E, F, temp;
4093
4094   sr_data = crdata[14];
4095
4096   /* Horizontal total */
4097   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
4098   A = HT + 5;
4099
4100   /* Horizontal display enable end */
4101   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
4102   E = HDE + 1;
4103
4104   /* Horizontal retrace (=sync) start */
4105   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
4106   F = HRS - E - 3;
4107
4108   /* Horizontal blank start */
4109   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
4110
4111   sr_data = crdata[15];
4112   cr_data = crdata[5];
4113
4114   /* Horizontal blank end */
4115   HBE = (crdata[3] & 0x1f) |
4116         ((unsigned short)(cr_data & 0x80) >> 2) |
4117         ((unsigned short)(sr_data & 0x03) << 6);
4118
4119   /* Horizontal retrace (=sync) end */
4120   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
4121
4122   temp = HBE - ((E - 1) & 255);
4123   B = (temp > 0) ? temp : (temp + 256);
4124
4125   temp = HRE - ((E + F + 3) & 63);
4126   C = (temp > 0) ? temp : (temp + 64);
4127
4128   D = B - F - C;
4129
4130#ifdef SIS_XORG_XF86
4131   current->HDisplay   = (E * 8);
4132   current->HSyncStart = (E * 8) + (F * 8);
4133   current->HSyncEnd   = (E * 8) + (F * 8) + (C * 8);
4134   current->HTotal     = (E * 8) + (F * 8) + (C * 8) + (D * 8);
4135#ifdef TWDEBUG
4136   xf86DrvMsg(0, X_INFO,
4137                "H: A %d B %d C %d D %d E %d F %d  HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
4138                A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
4139#else
4140   (void)VBS;  (void)HBS;  (void)A;
4141#endif
4142#endif
4143#ifdef SIS_LINUX_KERNEL
4144   if(writeres) var->xres = xres = E * 8;
4145   var->left_margin = D * 8;
4146   var->right_margin = F * 8;
4147   var->hsync_len = C * 8;
4148#endif
4149
4150   /* Vertical */
4151   sr_data = crdata[13];
4152   cr_data = crdata[7];
4153
4154   /* Vertical total */
4155   VT  = crdata[6] |
4156         ((unsigned short)(cr_data & 0x01) << 8) |
4157         ((unsigned short)(cr_data & 0x20) << 4) |
4158         ((unsigned short)(sr_data & 0x01) << 10);
4159   A = VT + 2;
4160
4161   /* Vertical display enable end */
4162   VDE = crdata[10] |
4163         ((unsigned short)(cr_data & 0x02) << 7) |
4164         ((unsigned short)(cr_data & 0x40) << 3) |
4165         ((unsigned short)(sr_data & 0x02) << 9);
4166   E = VDE + 1;
4167
4168   /* Vertical retrace (=sync) start */
4169   VRS = crdata[8] |
4170         ((unsigned short)(cr_data & 0x04) << 6) |
4171         ((unsigned short)(cr_data & 0x80) << 2) |
4172         ((unsigned short)(sr_data & 0x08) << 7);
4173   F = VRS + 1 - E;
4174
4175   cr_data2 = (crdata[16] & 0x01) << 5;
4176
4177   /* Vertical blank start */
4178   VBS = crdata[11] |
4179         ((unsigned short)(cr_data  & 0x08) << 5) |
4180         ((unsigned short)(cr_data2 & 0x20) << 4) |
4181         ((unsigned short)(sr_data  & 0x04) << 8);
4182
4183   /* Vertical blank end */
4184   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
4185   temp = VBE - ((E - 1) & 511);
4186   B = (temp > 0) ? temp : (temp + 512);
4187
4188   /* Vertical retrace (=sync) end */
4189   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
4190   temp = VRE - ((E + F - 1) & 31);
4191   C = (temp > 0) ? temp : (temp + 32);
4192
4193   D = B - F - C;
4194
4195#ifdef SIS_XORG_XF86
4196   current->VDisplay   = VDE + 1;
4197   current->VSyncStart = VRS + 1;
4198   current->VSyncEnd   = ((VRS & ~0x1f) | VRE) + 1;
4199   if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
4200   current->VTotal     = E + D + C + F;
4201#if 0
4202   current->VDisplay   = E;
4203   current->VSyncStart = E + D;
4204   current->VSyncEnd   = E + D + C;
4205   current->VTotal     = E + D + C + F;
4206#endif
4207#ifdef TWDEBUG
4208   xf86DrvMsg(0, X_INFO,
4209        "V: A %d B %d C %d D %d E %d F %d  VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
4210        A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
4211#endif
4212#endif
4213#ifdef SIS_LINUX_KERNEL
4214   if(writeres) var->yres = yres = E;
4215   var->upper_margin = D;
4216   var->lower_margin = F;
4217   var->vsync_len = C;
4218#endif
4219
4220   if((xres == 320) && ((yres == 200) || (yres == 240))) {
4221        /* Terrible hack, but correct CRTC data for
4222         * these modes only produces a black screen...
4223         * (HRE is 0, leading into a too large C and
4224         * a negative D. The CRT controller does not
4225         * seem to like correcting HRE to 50)
4226         */
4227#ifdef SIS_XORG_XF86
4228      current->HDisplay   = 320;
4229      current->HSyncStart = 328;
4230      current->HSyncEnd   = 376;
4231      current->HTotal     = 400;
4232#endif
4233#ifdef SIS_LINUX_KERNEL
4234      var->left_margin = (400 - 376);
4235      var->right_margin = (328 - 320);
4236      var->hsync_len = (376 - 328);
4237#endif
4238
4239   }
4240
4241}
4242
4243
4244
4245
4246