init.c revision 72b676d7
172b676d7Smrg/* $XFree86$ */
272b676d7Smrg/* $XdotOrg$ */
372b676d7Smrg/*
472b676d7Smrg * Mode initializing code (CRT1 section) for
572b676d7Smrg * for SiS 300/305/540/630/730,
672b676d7Smrg *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
772b676d7Smrg *     XGI Volari V3XT/V5/V8, Z7
872b676d7Smrg * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
972b676d7Smrg *
1072b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
1172b676d7Smrg *
1272b676d7Smrg * If distributed as part of the Linux kernel, the following license terms
1372b676d7Smrg * apply:
1472b676d7Smrg *
1572b676d7Smrg * * This program is free software; you can redistribute it and/or modify
1672b676d7Smrg * * it under the terms of the GNU General Public License as published by
1772b676d7Smrg * * the Free Software Foundation; either version 2 of the named License,
1872b676d7Smrg * * or any later version.
1972b676d7Smrg * *
2072b676d7Smrg * * This program is distributed in the hope that it will be useful,
2172b676d7Smrg * * but WITHOUT ANY WARRANTY; without even the implied warranty of
2272b676d7Smrg * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2372b676d7Smrg * * GNU General Public License for more details.
2472b676d7Smrg * *
2572b676d7Smrg * * You should have received a copy of the GNU General Public License
2672b676d7Smrg * * along with this program; if not, write to the Free Software
2772b676d7Smrg * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
2872b676d7Smrg *
2972b676d7Smrg * Otherwise, the following license terms apply:
3072b676d7Smrg *
3172b676d7Smrg * * Redistribution and use in source and binary forms, with or without
3272b676d7Smrg * * modification, are permitted provided that the following conditions
3372b676d7Smrg * * are met:
3472b676d7Smrg * * 1) Redistributions of source code must retain the above copyright
3572b676d7Smrg * *    notice, this list of conditions and the following disclaimer.
3672b676d7Smrg * * 2) Redistributions in binary form must reproduce the above copyright
3772b676d7Smrg * *    notice, this list of conditions and the following disclaimer in the
3872b676d7Smrg * *    documentation and/or other materials provided with the distribution.
3972b676d7Smrg * * 3) The name of the author may not be used to endorse or promote products
4072b676d7Smrg * *    derived from this software without specific prior written permission.
4172b676d7Smrg * *
4272b676d7Smrg * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4372b676d7Smrg * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4472b676d7Smrg * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4572b676d7Smrg * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4672b676d7Smrg * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4772b676d7Smrg * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4872b676d7Smrg * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4972b676d7Smrg * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5072b676d7Smrg * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5172b676d7Smrg * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5272b676d7Smrg *
5372b676d7Smrg * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
5472b676d7Smrg *
5572b676d7Smrg * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
5672b676d7Smrg * Used by permission.
5772b676d7Smrg */
5872b676d7Smrg
5972b676d7Smrg#ifdef HAVE_CONFIG_H
6072b676d7Smrg#include "config.h"
6172b676d7Smrg#endif
6272b676d7Smrg
6372b676d7Smrg#include "init.h"
6472b676d7Smrg
6572b676d7Smrg#ifdef SIS300
6672b676d7Smrg#include "300vtbl.h"
6772b676d7Smrg#endif
6872b676d7Smrg
6972b676d7Smrg#ifdef SIS315H
7072b676d7Smrg#include "310vtbl.h"
7172b676d7Smrg#endif
7272b676d7Smrg
7372b676d7Smrg#if defined(ALLOC_PRAGMA)
7472b676d7Smrg#pragma alloc_text(PAGE,SiSSetMode)
7572b676d7Smrg#endif
7672b676d7Smrg
7772b676d7Smrg/*********************************************/
7872b676d7Smrg/*         POINTER INITIALIZATION            */
7972b676d7Smrg/*********************************************/
8072b676d7Smrg
8172b676d7Smrg#if defined(SIS300) || defined(SIS315H)
8272b676d7Smrgstatic void
8372b676d7SmrgInitCommonPointer(struct SiS_Private *SiS_Pr)
8472b676d7Smrg{
8572b676d7Smrg   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
8672b676d7Smrg   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
8772b676d7Smrg   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
8872b676d7Smrg   SiS_Pr->SiS_StandTable    = SiS_StandTable;
8972b676d7Smrg
9072b676d7Smrg   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
9172b676d7Smrg   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
9272b676d7Smrg   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
9372b676d7Smrg   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
9472b676d7Smrg
9572b676d7Smrg   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
9672b676d7Smrg   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
9772b676d7Smrg   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
9872b676d7Smrg#if 0
9972b676d7Smrg   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
10072b676d7Smrg   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
10172b676d7Smrg#endif
10272b676d7Smrg
10372b676d7Smrg   SiS_Pr->SiS_StPALData   = SiS_StPALData;
10472b676d7Smrg   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
10572b676d7Smrg   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
10672b676d7Smrg   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
10772b676d7Smrg   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
10872b676d7Smrg   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
10972b676d7Smrg   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
11072b676d7Smrg   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
11172b676d7Smrg   SiS_Pr->SiS_St525pData  = SiS_St525pData;
11272b676d7Smrg   SiS_Pr->SiS_St625iData  = SiS_StPALData;
11372b676d7Smrg   SiS_Pr->SiS_St625pData  = SiS_StPALData;
11472b676d7Smrg   SiS_Pr->SiS_St750pData  = SiS_St750pData;
11572b676d7Smrg   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
11672b676d7Smrg   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
11772b676d7Smrg   SiS_Pr->SiS_Ext625iData = SiS_ExtPALData;
11872b676d7Smrg   SiS_Pr->SiS_Ext625pData = SiS_ExtPALData;
11972b676d7Smrg   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;
12072b676d7Smrg
12172b676d7Smrg   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
12272b676d7Smrg   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
12372b676d7Smrg
12472b676d7Smrg   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
12572b676d7Smrg   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
12672b676d7Smrg   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
12772b676d7Smrg   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
12872b676d7Smrg   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
12972b676d7Smrg   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
13072b676d7Smrg   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
13172b676d7Smrg   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
13272b676d7Smrg   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
13372b676d7Smrg   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
13472b676d7Smrg   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
13572b676d7Smrg   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
13672b676d7Smrg   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
13772b676d7Smrg
13872b676d7Smrg   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
13972b676d7Smrg   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
14072b676d7Smrg   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
14172b676d7Smrg   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
14272b676d7Smrg   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
14372b676d7Smrg   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
14472b676d7Smrg
14572b676d7Smrg   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
14672b676d7Smrg   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
14772b676d7Smrg   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
14872b676d7Smrg   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
14972b676d7Smrg   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
15072b676d7Smrg   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
15172b676d7Smrg   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
15272b676d7Smrg#if 0
15372b676d7Smrg   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
15472b676d7Smrg   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
15572b676d7Smrg   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
15672b676d7Smrg   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
15772b676d7Smrg#endif
15872b676d7Smrg
15972b676d7Smrg   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
16072b676d7Smrg   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
16172b676d7Smrg
16272b676d7Smrg   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
16372b676d7Smrg   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
16472b676d7Smrg}
16572b676d7Smrg#endif
16672b676d7Smrg
16772b676d7Smrg#ifdef SIS300
16872b676d7Smrgstatic void
16972b676d7SmrgInitTo300Pointer(struct SiS_Private *SiS_Pr)
17072b676d7Smrg{
17172b676d7Smrg   InitCommonPointer(SiS_Pr);
17272b676d7Smrg
17372b676d7Smrg   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
17472b676d7Smrg   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
17572b676d7Smrg   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
17672b676d7Smrg   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
17772b676d7Smrg   if(SiS_Pr->ChipType == SIS_300) {
17872b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
17972b676d7Smrg   } else {
18072b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
18172b676d7Smrg   }
18272b676d7Smrg   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
18372b676d7Smrg   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;
18472b676d7Smrg
18572b676d7Smrg   SiS_Pr->SiS_SR15  = SiS300_SR15;
18672b676d7Smrg
18772b676d7Smrg   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
18872b676d7Smrg   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
18972b676d7Smrg
19072b676d7Smrg   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
19172b676d7Smrg   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
19272b676d7Smrg   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
19372b676d7Smrg   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
19472b676d7Smrg
19572b676d7Smrg   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
19672b676d7Smrg   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
19772b676d7Smrg   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
19872b676d7Smrg
19972b676d7Smrg   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
20072b676d7Smrg   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
20172b676d7Smrg   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
20272b676d7Smrg   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
20372b676d7Smrg   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
20472b676d7Smrg   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
20572b676d7Smrg   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
20672b676d7Smrg
20772b676d7Smrg   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
20872b676d7Smrg   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
20972b676d7Smrg   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
21072b676d7Smrg   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
21172b676d7Smrg   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
21272b676d7Smrg
21372b676d7Smrg   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
21472b676d7Smrg   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
21572b676d7Smrg   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
21672b676d7Smrg   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
21772b676d7Smrg
21872b676d7Smrg   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
21972b676d7Smrg   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
22072b676d7Smrg   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
22172b676d7Smrg   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
22272b676d7Smrg   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
22372b676d7Smrg   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
22472b676d7Smrg   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
22572b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
22672b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
22772b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
22872b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
22972b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
23072b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
23172b676d7Smrg   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
23272b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
23372b676d7Smrg   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
23472b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
23572b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;
23672b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */
23772b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */
23872b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
23972b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
24072b676d7Smrg   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
24172b676d7Smrg}
24272b676d7Smrg#endif
24372b676d7Smrg
24472b676d7Smrg#ifdef SIS315H
24572b676d7Smrgstatic void
24672b676d7SmrgInitTo310Pointer(struct SiS_Private *SiS_Pr)
24772b676d7Smrg{
24872b676d7Smrg   InitCommonPointer(SiS_Pr);
24972b676d7Smrg
25072b676d7Smrg   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
25172b676d7Smrg   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
25272b676d7Smrg   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
25372b676d7Smrg   if(SiS_Pr->ChipType >= SIS_340) {
25472b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
25572b676d7Smrg   } else if(SiS_Pr->ChipType >= SIS_761) {
25672b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
25772b676d7Smrg   } else if(SiS_Pr->ChipType >= SIS_760) {
25872b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
25972b676d7Smrg   } else if(SiS_Pr->ChipType >= SIS_661) {
26072b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
26172b676d7Smrg   } else if(SiS_Pr->ChipType == SIS_330) {
26272b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
26372b676d7Smrg   } else if(SiS_Pr->ChipType > SIS_315PRO) {
26472b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
26572b676d7Smrg   } else {
26672b676d7Smrg      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
26772b676d7Smrg   }
26872b676d7Smrg   if(SiS_Pr->ChipType >= SIS_340) {
26972b676d7Smrg      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
27072b676d7Smrg   } else {
27172b676d7Smrg      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
27272b676d7Smrg   }
27372b676d7Smrg   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
27472b676d7Smrg   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
27572b676d7Smrg
27672b676d7Smrg   SiS_Pr->SiS_SR15  = SiS310_SR15;
27772b676d7Smrg
27872b676d7Smrg   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
27972b676d7Smrg   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
28072b676d7Smrg
28172b676d7Smrg   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
28272b676d7Smrg   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
28372b676d7Smrg   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
28472b676d7Smrg   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
28572b676d7Smrg
28672b676d7Smrg   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
28772b676d7Smrg
28872b676d7Smrg   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
28972b676d7Smrg   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
29072b676d7Smrg   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
29172b676d7Smrg   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
29272b676d7Smrg   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
29372b676d7Smrg   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
29472b676d7Smrg   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
29572b676d7Smrg
29672b676d7Smrg   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
29772b676d7Smrg   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
29872b676d7Smrg   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
29972b676d7Smrg   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
30072b676d7Smrg   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
30172b676d7Smrg
30272b676d7Smrg   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
30372b676d7Smrg   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
30472b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
30572b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
30672b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
30772b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
30872b676d7Smrg   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
30972b676d7Smrg   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
31072b676d7Smrg   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
31172b676d7Smrg
31272b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
31372b676d7Smrg   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
31472b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
31572b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;
31672b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
31772b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
31872b676d7Smrg   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
31972b676d7Smrg   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
32072b676d7Smrg   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
32172b676d7Smrg}
32272b676d7Smrg#endif
32372b676d7Smrg
32472b676d7SmrgBOOLEAN
32572b676d7SmrgSiSInitPtr(struct SiS_Private *SiS_Pr)
32672b676d7Smrg{
32772b676d7Smrg   if(SiS_Pr->ChipType < SIS_315H) {
32872b676d7Smrg#ifdef SIS300
32972b676d7Smrg      InitTo300Pointer(SiS_Pr);
33072b676d7Smrg#else
33172b676d7Smrg      return FALSE;
33272b676d7Smrg#endif
33372b676d7Smrg   } else {
33472b676d7Smrg#ifdef SIS315H
33572b676d7Smrg      InitTo310Pointer(SiS_Pr);
33672b676d7Smrg#else
33772b676d7Smrg      return FALSE;
33872b676d7Smrg#endif
33972b676d7Smrg   }
34072b676d7Smrg   return TRUE;
34172b676d7Smrg}
34272b676d7Smrg
34372b676d7Smrg/*********************************************/
34472b676d7Smrg/*            HELPER: Get ModeID             */
34572b676d7Smrg/*********************************************/
34672b676d7Smrg
34772b676d7Smrg#ifndef SIS_XORG_XF86
34872b676d7Smrgstatic
34972b676d7Smrg#endif
35072b676d7Smrgunsigned short
35172b676d7SmrgSiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
35272b676d7Smrg		int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
35372b676d7Smrg{
35472b676d7Smrg   unsigned short ModeIndex = 0;
35572b676d7Smrg
35672b676d7Smrg   switch(HDisplay)
35772b676d7Smrg   {
35872b676d7Smrg	case 320:
35972b676d7Smrg		if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
36072b676d7Smrg		else if(VDisplay == 240) {
36172b676d7Smrg			if((VBFlags & CRT2_LCD) && (FSTN))
36272b676d7Smrg				ModeIndex = ModeIndex_320x240_FSTN[Depth];
36372b676d7Smrg			else
36472b676d7Smrg				ModeIndex = ModeIndex_320x240[Depth];
36572b676d7Smrg		}
36672b676d7Smrg		break;
36772b676d7Smrg	case 400:
36872b676d7Smrg		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
36972b676d7Smrg			if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
37072b676d7Smrg		}
37172b676d7Smrg		break;
37272b676d7Smrg	case 512:
37372b676d7Smrg		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
37472b676d7Smrg			if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
37572b676d7Smrg		}
37672b676d7Smrg		break;
37772b676d7Smrg	case 640:
37872b676d7Smrg		if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
37972b676d7Smrg		else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
38072b676d7Smrg		break;
38172b676d7Smrg	case 720:
38272b676d7Smrg		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
38372b676d7Smrg		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
38472b676d7Smrg		break;
38572b676d7Smrg	case 768:
38672b676d7Smrg		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
38772b676d7Smrg		break;
38872b676d7Smrg	case 800:
38972b676d7Smrg		if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
39072b676d7Smrg		else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
39172b676d7Smrg		break;
39272b676d7Smrg	case 848:
39372b676d7Smrg		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
39472b676d7Smrg		break;
39572b676d7Smrg	case 856:
39672b676d7Smrg		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
39772b676d7Smrg		break;
39872b676d7Smrg	case 960:
39972b676d7Smrg		if(VGAEngine == SIS_315_VGA) {
40072b676d7Smrg			if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
40172b676d7Smrg			else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
40272b676d7Smrg		}
40372b676d7Smrg		break;
40472b676d7Smrg	case 1024:
40572b676d7Smrg		if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
40672b676d7Smrg		else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
40772b676d7Smrg		else if(VGAEngine == SIS_300_VGA) {
40872b676d7Smrg			if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
40972b676d7Smrg		}
41072b676d7Smrg		break;
41172b676d7Smrg	case 1152:
41272b676d7Smrg		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
41372b676d7Smrg		if(VGAEngine == SIS_300_VGA) {
41472b676d7Smrg			if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
41572b676d7Smrg		}
41672b676d7Smrg		break;
41772b676d7Smrg	case 1280:
41872b676d7Smrg		switch(VDisplay) {
41972b676d7Smrg			case 720:
42072b676d7Smrg				ModeIndex = ModeIndex_1280x720[Depth];
42172b676d7Smrg				break;
42272b676d7Smrg			case 768:
42372b676d7Smrg				if(VGAEngine == SIS_300_VGA) {
42472b676d7Smrg					ModeIndex = ModeIndex_300_1280x768[Depth];
42572b676d7Smrg				} else {
42672b676d7Smrg					ModeIndex = ModeIndex_310_1280x768[Depth];
42772b676d7Smrg				}
42872b676d7Smrg				break;
42972b676d7Smrg			case 800:
43072b676d7Smrg				if(VGAEngine == SIS_315_VGA) {
43172b676d7Smrg					ModeIndex = ModeIndex_1280x800[Depth];
43272b676d7Smrg				}
43372b676d7Smrg				break;
43472b676d7Smrg			case 854:
43572b676d7Smrg				if(VGAEngine == SIS_315_VGA) {
43672b676d7Smrg					ModeIndex = ModeIndex_1280x854[Depth];
43772b676d7Smrg				}
43872b676d7Smrg				break;
43972b676d7Smrg			case 960:
44072b676d7Smrg				ModeIndex = ModeIndex_1280x960[Depth];
44172b676d7Smrg				break;
44272b676d7Smrg			case 1024:
44372b676d7Smrg				ModeIndex = ModeIndex_1280x1024[Depth];
44472b676d7Smrg				break;
44572b676d7Smrg		}
44672b676d7Smrg		break;
44772b676d7Smrg	case 1360:
44872b676d7Smrg		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
44972b676d7Smrg		if(VGAEngine == SIS_300_VGA) {
45072b676d7Smrg			if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
45172b676d7Smrg		}
45272b676d7Smrg		break;
45372b676d7Smrg	case 1400:
45472b676d7Smrg		if(VGAEngine == SIS_315_VGA) {
45572b676d7Smrg			if(VDisplay == 1050) {
45672b676d7Smrg				ModeIndex = ModeIndex_1400x1050[Depth];
45772b676d7Smrg			}
45872b676d7Smrg		}
45972b676d7Smrg		break;
46072b676d7Smrg	case 1600:
46172b676d7Smrg		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
46272b676d7Smrg		break;
46372b676d7Smrg	case 1680:
46472b676d7Smrg		if(VGAEngine == SIS_315_VGA) {
46572b676d7Smrg			if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
46672b676d7Smrg		}
46772b676d7Smrg		break;
46872b676d7Smrg	case 1920:
46972b676d7Smrg		if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
47072b676d7Smrg		else if(VGAEngine == SIS_315_VGA) {
47172b676d7Smrg			if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
47272b676d7Smrg		}
47372b676d7Smrg		break;
47472b676d7Smrg	case 2048:
47572b676d7Smrg		if(VDisplay == 1536) {
47672b676d7Smrg			if(VGAEngine == SIS_300_VGA) {
47772b676d7Smrg				ModeIndex = ModeIndex_300_2048x1536[Depth];
47872b676d7Smrg			} else {
47972b676d7Smrg				ModeIndex = ModeIndex_310_2048x1536[Depth];
48072b676d7Smrg			}
48172b676d7Smrg		}
48272b676d7Smrg		break;
48372b676d7Smrg   }
48472b676d7Smrg
48572b676d7Smrg   return ModeIndex;
48672b676d7Smrg}
48772b676d7Smrg
48872b676d7Smrgunsigned short
48972b676d7SmrgSiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
49072b676d7Smrg		int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
49172b676d7Smrg		unsigned int VBFlags2)
49272b676d7Smrg{
49372b676d7Smrg   unsigned short ModeIndex = 0;
49472b676d7Smrg
49572b676d7Smrg   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
49672b676d7Smrg
49772b676d7Smrg      switch(HDisplay)
49872b676d7Smrg      {
49972b676d7Smrg	case 320:
50072b676d7Smrg	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
50172b676d7Smrg		if(VDisplay == 200) {
50272b676d7Smrg		   if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
50372b676d7Smrg		} else if(VDisplay == 240) {
50472b676d7Smrg		   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
50572b676d7Smrg		   else if(VGAEngine == SIS_315_VGA) {
50672b676d7Smrg		      ModeIndex = ModeIndex_320x240_FSTN[Depth];
50772b676d7Smrg		   }
50872b676d7Smrg		}
50972b676d7Smrg	     }
51072b676d7Smrg	     break;
51172b676d7Smrg	case 400:
51272b676d7Smrg	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
51372b676d7Smrg		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
51472b676d7Smrg		   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
51572b676d7Smrg		}
51672b676d7Smrg	     }
51772b676d7Smrg	     break;
51872b676d7Smrg	case 512:
51972b676d7Smrg	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
52072b676d7Smrg		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
52172b676d7Smrg		   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
52272b676d7Smrg		      if(VDisplay == 384) {
52372b676d7Smrg		         ModeIndex = ModeIndex_512x384[Depth];
52472b676d7Smrg		      }
52572b676d7Smrg		   }
52672b676d7Smrg		}
52772b676d7Smrg	     }
52872b676d7Smrg	     break;
52972b676d7Smrg	case 640:
53072b676d7Smrg	     if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
53172b676d7Smrg	     else if(VDisplay == 400) {
53272b676d7Smrg		if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
53372b676d7Smrg		   ModeIndex = ModeIndex_640x400[Depth];
53472b676d7Smrg	     }
53572b676d7Smrg	     break;
53672b676d7Smrg	case 800:
53772b676d7Smrg	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
53872b676d7Smrg	     break;
53972b676d7Smrg	case 848:
54072b676d7Smrg	     if(CustomT == CUT_PANEL848) {
54172b676d7Smrg	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
54272b676d7Smrg	     }
54372b676d7Smrg	     break;
54472b676d7Smrg	case 856:
54572b676d7Smrg	     if(CustomT == CUT_PANEL856) {
54672b676d7Smrg	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
54772b676d7Smrg	     }
54872b676d7Smrg	     break;
54972b676d7Smrg	case 1024:
55072b676d7Smrg	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
55172b676d7Smrg	     else if(VGAEngine == SIS_300_VGA) {
55272b676d7Smrg		if((VDisplay == 600) && (LCDheight == 600)) {
55372b676d7Smrg		   ModeIndex = ModeIndex_1024x600[Depth];
55472b676d7Smrg		}
55572b676d7Smrg	     }
55672b676d7Smrg	     break;
55772b676d7Smrg	case 1152:
55872b676d7Smrg	     if(VGAEngine == SIS_300_VGA) {
55972b676d7Smrg		if((VDisplay == 768) && (LCDheight == 768)) {
56072b676d7Smrg		   ModeIndex = ModeIndex_1152x768[Depth];
56172b676d7Smrg		}
56272b676d7Smrg	     }
56372b676d7Smrg	     break;
56472b676d7Smrg        case 1280:
56572b676d7Smrg	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
56672b676d7Smrg	     else if(VGAEngine == SIS_315_VGA) {
56772b676d7Smrg		if((VDisplay == 768) && (LCDheight == 768)) {
56872b676d7Smrg		   ModeIndex = ModeIndex_310_1280x768[Depth];
56972b676d7Smrg		}
57072b676d7Smrg	     }
57172b676d7Smrg	     break;
57272b676d7Smrg	case 1360:
57372b676d7Smrg	     if(VGAEngine == SIS_300_VGA) {
57472b676d7Smrg		if(CustomT == CUT_BARCO1366) {
57572b676d7Smrg		   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
57672b676d7Smrg		}
57772b676d7Smrg	     }
57872b676d7Smrg	     if(CustomT == CUT_PANEL848) {
57972b676d7Smrg		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
58072b676d7Smrg	     }
58172b676d7Smrg	     break;
58272b676d7Smrg	case 1400:
58372b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
58472b676d7Smrg		if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
58572b676d7Smrg	     }
58672b676d7Smrg	     break;
58772b676d7Smrg	case 1600:
58872b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
58972b676d7Smrg		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
59072b676d7Smrg	     }
59172b676d7Smrg	     break;
59272b676d7Smrg      }
59372b676d7Smrg
59472b676d7Smrg   } else if(VBFlags2 & VB2_SISBRIDGE) {
59572b676d7Smrg
59672b676d7Smrg      switch(HDisplay)
59772b676d7Smrg      {
59872b676d7Smrg	case 320:
59972b676d7Smrg	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
60072b676d7Smrg	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
60172b676d7Smrg	     break;
60272b676d7Smrg	case 400:
60372b676d7Smrg	     if(LCDwidth >= 800 && LCDheight >= 600) {
60472b676d7Smrg		if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
60572b676d7Smrg	     }
60672b676d7Smrg	     break;
60772b676d7Smrg	case 512:
60872b676d7Smrg	     if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
60972b676d7Smrg		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
61072b676d7Smrg	     }
61172b676d7Smrg	     break;
61272b676d7Smrg	case 640:
61372b676d7Smrg	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
61472b676d7Smrg	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
61572b676d7Smrg	     break;
61672b676d7Smrg	case 720:
61772b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
61872b676d7Smrg		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
61972b676d7Smrg		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
62072b676d7Smrg	     }
62172b676d7Smrg	     break;
62272b676d7Smrg	case 768:
62372b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
62472b676d7Smrg		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
62572b676d7Smrg	     }
62672b676d7Smrg	     break;
62772b676d7Smrg	case 800:
62872b676d7Smrg	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
62972b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
63072b676d7Smrg		if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
63172b676d7Smrg	     }
63272b676d7Smrg	     break;
63372b676d7Smrg	case 848:
63472b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
63572b676d7Smrg		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
63672b676d7Smrg	     }
63772b676d7Smrg	     break;
63872b676d7Smrg	case 856:
63972b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
64072b676d7Smrg		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
64172b676d7Smrg	     }
64272b676d7Smrg	     break;
64372b676d7Smrg	case 960:
64472b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
64572b676d7Smrg		if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
64672b676d7Smrg		else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
64772b676d7Smrg	     }
64872b676d7Smrg	     break;
64972b676d7Smrg	case 1024:
65072b676d7Smrg	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
65172b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
65272b676d7Smrg		if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
65372b676d7Smrg	     }
65472b676d7Smrg	     break;
65572b676d7Smrg	case 1152:
65672b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
65772b676d7Smrg		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
65872b676d7Smrg	     }
65972b676d7Smrg	     break;
66072b676d7Smrg	case 1280:
66172b676d7Smrg	     switch(VDisplay) {
66272b676d7Smrg	     case 720:
66372b676d7Smrg		ModeIndex = ModeIndex_1280x720[Depth];
66472b676d7Smrg	     case 768:
66572b676d7Smrg		if(VGAEngine == SIS_300_VGA) {
66672b676d7Smrg		   ModeIndex = ModeIndex_300_1280x768[Depth];
66772b676d7Smrg		} else {
66872b676d7Smrg		   ModeIndex = ModeIndex_310_1280x768[Depth];
66972b676d7Smrg		}
67072b676d7Smrg		break;
67172b676d7Smrg	     case 800:
67272b676d7Smrg		if(VGAEngine == SIS_315_VGA) {
67372b676d7Smrg		   ModeIndex = ModeIndex_1280x800[Depth];
67472b676d7Smrg		}
67572b676d7Smrg		break;
67672b676d7Smrg	     case 854:
67772b676d7Smrg		if(VGAEngine == SIS_315_VGA) {
67872b676d7Smrg		   ModeIndex = ModeIndex_1280x854[Depth];
67972b676d7Smrg		}
68072b676d7Smrg		break;
68172b676d7Smrg	     case 960:
68272b676d7Smrg		ModeIndex = ModeIndex_1280x960[Depth];
68372b676d7Smrg		break;
68472b676d7Smrg	     case 1024:
68572b676d7Smrg		ModeIndex = ModeIndex_1280x1024[Depth];
68672b676d7Smrg		break;
68772b676d7Smrg	     }
68872b676d7Smrg	     break;
68972b676d7Smrg	case 1360:
69072b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
69172b676d7Smrg		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
69272b676d7Smrg	     }
69372b676d7Smrg	     break;
69472b676d7Smrg	case 1400:
69572b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
69672b676d7Smrg		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
69772b676d7Smrg		   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
69872b676d7Smrg		}
69972b676d7Smrg	     }
70072b676d7Smrg	     break;
70172b676d7Smrg	case 1600:
70272b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
70372b676d7Smrg		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
70472b676d7Smrg		   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
70572b676d7Smrg		}
70672b676d7Smrg	     }
70772b676d7Smrg	     break;
70872b676d7Smrg#ifndef VB_FORBID_CRT2LCD_OVER_1600
70972b676d7Smrg	case 1680:
71072b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
71172b676d7Smrg		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
71272b676d7Smrg		   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
71372b676d7Smrg		}
71472b676d7Smrg	     }
71572b676d7Smrg	     break;
71672b676d7Smrg	case 1920:
71772b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
71872b676d7Smrg		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
71972b676d7Smrg		   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
72072b676d7Smrg		}
72172b676d7Smrg	     }
72272b676d7Smrg	     break;
72372b676d7Smrg	case 2048:
72472b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
72572b676d7Smrg		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
72672b676d7Smrg		   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
72772b676d7Smrg		}
72872b676d7Smrg	     }
72972b676d7Smrg	     break;
73072b676d7Smrg#endif
73172b676d7Smrg      }
73272b676d7Smrg   }
73372b676d7Smrg
73472b676d7Smrg   return ModeIndex;
73572b676d7Smrg}
73672b676d7Smrg
73772b676d7Smrgunsigned short
73872b676d7SmrgSiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
73972b676d7Smrg			unsigned int VBFlags2)
74072b676d7Smrg{
74172b676d7Smrg   unsigned short ModeIndex = 0;
74272b676d7Smrg
74372b676d7Smrg   if(VBFlags2 & VB2_CHRONTEL) {
74472b676d7Smrg
74572b676d7Smrg      switch(HDisplay)
74672b676d7Smrg      {
74772b676d7Smrg	case 512:
74872b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
74972b676d7Smrg		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
75072b676d7Smrg	     }
75172b676d7Smrg	     break;
75272b676d7Smrg	case 640:
75372b676d7Smrg	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
75472b676d7Smrg	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
75572b676d7Smrg	     break;
75672b676d7Smrg	case 800:
75772b676d7Smrg	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
75872b676d7Smrg	     break;
75972b676d7Smrg	case 1024:
76072b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
76172b676d7Smrg		if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
76272b676d7Smrg	     }
76372b676d7Smrg	     break;
76472b676d7Smrg      }
76572b676d7Smrg
76672b676d7Smrg   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
76772b676d7Smrg
76872b676d7Smrg      switch(HDisplay)
76972b676d7Smrg      {
77072b676d7Smrg	case 320:
77172b676d7Smrg	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
77272b676d7Smrg	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
77372b676d7Smrg	     break;
77472b676d7Smrg	case 400:
77572b676d7Smrg	     if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
77672b676d7Smrg	     break;
77772b676d7Smrg	case 512:
77872b676d7Smrg	     if(VBFlags2 & VB2_30xBLV) {
77972b676d7Smrg	        if( ((VBFlags & TV_YPBPR) && (!(VBFlags & (TV_YPBPR525P | TV_YPBPR525I)))) ||
78072b676d7Smrg		    (VBFlags & TV_HIVISION) 						||
78172b676d7Smrg		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
78272b676d7Smrg		   if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
78372b676d7Smrg	        }
78472b676d7Smrg	     }
78572b676d7Smrg	     break;
78672b676d7Smrg	case 640:
78772b676d7Smrg	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
78872b676d7Smrg	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
78972b676d7Smrg	     break;
79072b676d7Smrg	case 720:
79172b676d7Smrg	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
79272b676d7Smrg		if(VDisplay == 480) {
79372b676d7Smrg		   ModeIndex = ModeIndex_720x480[Depth];
79472b676d7Smrg		} else if(VDisplay == 576) {
79572b676d7Smrg		   ModeIndex = ModeIndex_720x576[Depth];
79672b676d7Smrg		}
79772b676d7Smrg	     }
79872b676d7Smrg             break;
79972b676d7Smrg	case 768:
80072b676d7Smrg	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
80172b676d7Smrg		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
80272b676d7Smrg             }
80372b676d7Smrg	     break;
80472b676d7Smrg	case 800:
80572b676d7Smrg	     if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
80672b676d7Smrg	     else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
80772b676d7Smrg	     break;
80872b676d7Smrg	case 960:
80972b676d7Smrg	     if(VGAEngine == SIS_315_VGA) {
81072b676d7Smrg	        if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
81172b676d7Smrg		   if(VDisplay == 600) {
81272b676d7Smrg		      ModeIndex = ModeIndex_960x600[Depth];
81372b676d7Smrg		   } else if(VDisplay == 540) {
81472b676d7Smrg		      ModeIndex = ModeIndex_960x540[Depth];
81572b676d7Smrg		   }
81672b676d7Smrg		}
81772b676d7Smrg	     }
81872b676d7Smrg	     break;
81972b676d7Smrg	case 1024:
82072b676d7Smrg	     if((VBFlags2 & VB2_30xBLV) ||
82172b676d7Smrg	        (VBFlags & TV_HIVISION) ||
82272b676d7Smrg	        ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
82372b676d7Smrg	        if(VDisplay == 768) {
82472b676d7Smrg		   ModeIndex = ModeIndex_1024x768[Depth];
82572b676d7Smrg		} else if(VDisplay == 576) {
82672b676d7Smrg		   ModeIndex = ModeIndex_1024x576[Depth];
82772b676d7Smrg		}
82872b676d7Smrg	     }
82972b676d7Smrg	     break;
83072b676d7Smrg	case 1280:
83172b676d7Smrg	     if(VDisplay == 720) {
83272b676d7Smrg		if((VBFlags & TV_HIVISION) ||
83372b676d7Smrg		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
83472b676d7Smrg		   ModeIndex = ModeIndex_1280x720[Depth];
83572b676d7Smrg		}
83672b676d7Smrg	     } else if(VDisplay == 1024) {
83772b676d7Smrg		if((VBFlags & TV_HIVISION) ||
83872b676d7Smrg		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
83972b676d7Smrg		   ModeIndex = ModeIndex_1280x1024[Depth];
84072b676d7Smrg		}
84172b676d7Smrg	     }
84272b676d7Smrg	     break;
84372b676d7Smrg      }
84472b676d7Smrg   }
84572b676d7Smrg   return ModeIndex;
84672b676d7Smrg}
84772b676d7Smrg
84872b676d7Smrgunsigned short
84972b676d7SmrgSiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
85072b676d7Smrg			unsigned int VBFlags2)
85172b676d7Smrg{
85272b676d7Smrg   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
85372b676d7Smrg
85472b676d7Smrg   if(HDisplay >= 1920) return 0;
85572b676d7Smrg
85672b676d7Smrg   switch(HDisplay)
85772b676d7Smrg   {
85872b676d7Smrg	case 1600:
85972b676d7Smrg		if(VDisplay == 1200) {
86072b676d7Smrg			if(VGAEngine != SIS_315_VGA) return 0;
86172b676d7Smrg			if(!(VBFlags2 & VB2_30xB)) return 0;
86272b676d7Smrg		}
86372b676d7Smrg		break;
86472b676d7Smrg	case 1680:
86572b676d7Smrg		if(VDisplay == 1050) {
86672b676d7Smrg			if(VGAEngine != SIS_315_VGA) return 0;
86772b676d7Smrg			if(!(VBFlags2 & VB2_30xB)) return 0;
86872b676d7Smrg		}
86972b676d7Smrg		break;
87072b676d7Smrg   }
87172b676d7Smrg
87272b676d7Smrg   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
87372b676d7Smrg}
87472b676d7Smrg
87572b676d7Smrg
87672b676d7Smrg/*********************************************/
87772b676d7Smrg/*          HELPER: SetReg, GetReg           */
87872b676d7Smrg/*********************************************/
87972b676d7Smrg
88072b676d7Smrgvoid
88172b676d7SmrgSiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
88272b676d7Smrg{
88372b676d7Smrg   OutPortByte(port, index);
88472b676d7Smrg   OutPortByte(port + 1, data);
88572b676d7Smrg}
88672b676d7Smrg
88772b676d7Smrgvoid
88872b676d7SmrgSiS_SetRegByte(SISIOADDRESS port, unsigned short data)
88972b676d7Smrg{
89072b676d7Smrg   OutPortByte(port, data);
89172b676d7Smrg}
89272b676d7Smrg
89372b676d7Smrgvoid
89472b676d7SmrgSiS_SetRegShort(SISIOADDRESS port, unsigned short data)
89572b676d7Smrg{
89672b676d7Smrg   OutPortWord(port, data);
89772b676d7Smrg}
89872b676d7Smrg
89972b676d7Smrgvoid
90072b676d7SmrgSiS_SetRegLong(SISIOADDRESS port, unsigned int data)
90172b676d7Smrg{
90272b676d7Smrg   OutPortLong(port, data);
90372b676d7Smrg}
90472b676d7Smrg
90572b676d7Smrgunsigned char
90672b676d7SmrgSiS_GetReg(SISIOADDRESS port, unsigned short index)
90772b676d7Smrg{
90872b676d7Smrg   OutPortByte(port, index);
90972b676d7Smrg   return(InPortByte(port + 1));
91072b676d7Smrg}
91172b676d7Smrg
91272b676d7Smrgunsigned char
91372b676d7SmrgSiS_GetRegByte(SISIOADDRESS port)
91472b676d7Smrg{
91572b676d7Smrg   return(InPortByte(port));
91672b676d7Smrg}
91772b676d7Smrg
91872b676d7Smrgunsigned short
91972b676d7SmrgSiS_GetRegShort(SISIOADDRESS port)
92072b676d7Smrg{
92172b676d7Smrg   return(InPortWord(port));
92272b676d7Smrg}
92372b676d7Smrg
92472b676d7Smrgunsigned int
92572b676d7SmrgSiS_GetRegLong(SISIOADDRESS port)
92672b676d7Smrg{
92772b676d7Smrg   return(InPortLong(port));
92872b676d7Smrg}
92972b676d7Smrg
93072b676d7Smrgvoid
93172b676d7SmrgSiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
93272b676d7Smrg{
93372b676d7Smrg   unsigned short temp;
93472b676d7Smrg
93572b676d7Smrg   temp = SiS_GetReg(Port, Index);
93672b676d7Smrg   temp = (temp & (DataAND)) | DataOR;
93772b676d7Smrg   SiS_SetReg(Port, Index, temp);
93872b676d7Smrg}
93972b676d7Smrg
94072b676d7Smrgvoid
94172b676d7SmrgSiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
94272b676d7Smrg{
94372b676d7Smrg   unsigned short temp;
94472b676d7Smrg
94572b676d7Smrg   temp = SiS_GetReg(Port, Index);
94672b676d7Smrg   temp &= DataAND;
94772b676d7Smrg   SiS_SetReg(Port, Index, temp);
94872b676d7Smrg}
94972b676d7Smrg
95072b676d7Smrgvoid
95172b676d7SmrgSiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
95272b676d7Smrg{
95372b676d7Smrg   unsigned short temp;
95472b676d7Smrg
95572b676d7Smrg   temp = SiS_GetReg(Port, Index);
95672b676d7Smrg   temp |= DataOR;
95772b676d7Smrg   SiS_SetReg(Port, Index, temp);
95872b676d7Smrg}
95972b676d7Smrg
96072b676d7Smrg/*********************************************/
96172b676d7Smrg/*      HELPER: DisplayOn, DisplayOff        */
96272b676d7Smrg/*********************************************/
96372b676d7Smrg
96472b676d7Smrgvoid
96572b676d7SmrgSiS_DisplayOn(struct SiS_Private *SiS_Pr)
96672b676d7Smrg{
96772b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
96872b676d7Smrg}
96972b676d7Smrg
97072b676d7Smrgvoid
97172b676d7SmrgSiS_DisplayOff(struct SiS_Private *SiS_Pr)
97272b676d7Smrg{
97372b676d7Smrg   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
97472b676d7Smrg}
97572b676d7Smrg
97672b676d7Smrg
97772b676d7Smrg/*********************************************/
97872b676d7Smrg/*        HELPER: Init Port Addresses        */
97972b676d7Smrg/*********************************************/
98072b676d7Smrg
98172b676d7Smrgvoid
98272b676d7SmrgSiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
98372b676d7Smrg{
98472b676d7Smrg   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
98572b676d7Smrg   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
98672b676d7Smrg   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
98772b676d7Smrg   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
98872b676d7Smrg   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
98972b676d7Smrg   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
99072b676d7Smrg   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
99172b676d7Smrg   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
99272b676d7Smrg   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
99372b676d7Smrg   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
99472b676d7Smrg   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
99572b676d7Smrg   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
99672b676d7Smrg   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
99772b676d7Smrg   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
99872b676d7Smrg   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
99972b676d7Smrg   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
100072b676d7Smrg   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
100172b676d7Smrg   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
100272b676d7Smrg   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
100372b676d7Smrg   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
100472b676d7Smrg   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
100572b676d7Smrg   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
100672b676d7Smrg}
100772b676d7Smrg
100872b676d7Smrg/*********************************************/
100972b676d7Smrg/*             HELPER: GetSysFlags           */
101072b676d7Smrg/*********************************************/
101172b676d7Smrg
101272b676d7Smrgstatic void
101372b676d7SmrgSiS_GetSysFlags(struct SiS_Private *SiS_Pr)
101472b676d7Smrg{
101572b676d7Smrg   unsigned char cr5f, temp1, temp2;
101672b676d7Smrg
101772b676d7Smrg   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
101872b676d7Smrg   /* (SR11 is used for DDC and in enable/disablebridge) */
101972b676d7Smrg   SiS_Pr->SiS_SensibleSR11 = FALSE;
102072b676d7Smrg   SiS_Pr->SiS_MyCR63 = 0x63;
102172b676d7Smrg   if(SiS_Pr->ChipType >= SIS_330) {
102272b676d7Smrg      SiS_Pr->SiS_MyCR63 = 0x53;
102372b676d7Smrg      if(SiS_Pr->ChipType >= SIS_661) {
102472b676d7Smrg         SiS_Pr->SiS_SensibleSR11 = TRUE;
102572b676d7Smrg      }
102672b676d7Smrg   }
102772b676d7Smrg
102872b676d7Smrg   /* You should use the macros, not these flags directly */
102972b676d7Smrg
103072b676d7Smrg   SiS_Pr->SiS_SysFlags = 0;
103172b676d7Smrg   if(SiS_Pr->ChipType == SIS_650) {
103272b676d7Smrg      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
103372b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
103472b676d7Smrg      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
103572b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
103672b676d7Smrg      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
103772b676d7Smrg      if((!temp1) || (temp2)) {
103872b676d7Smrg	 switch(cr5f) {
103972b676d7Smrg	    case 0x80:
104072b676d7Smrg	    case 0x90:
104172b676d7Smrg	    case 0xc0:
104272b676d7Smrg	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
104372b676d7Smrg	       break;
104472b676d7Smrg	    case 0xa0:
104572b676d7Smrg	    case 0xb0:
104672b676d7Smrg	    case 0xe0:
104772b676d7Smrg	       SiS_Pr->SiS_SysFlags |= SF_Is651;
104872b676d7Smrg	       break;
104972b676d7Smrg	 }
105072b676d7Smrg      } else {
105172b676d7Smrg	 switch(cr5f) {
105272b676d7Smrg	    case 0x90:
105372b676d7Smrg	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
105472b676d7Smrg	       switch(temp1) {
105572b676d7Smrg		  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
105672b676d7Smrg		  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
105772b676d7Smrg		  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
105872b676d7Smrg	       }
105972b676d7Smrg	       break;
106072b676d7Smrg	    case 0xb0:
106172b676d7Smrg	       SiS_Pr->SiS_SysFlags |= SF_Is652;
106272b676d7Smrg	       break;
106372b676d7Smrg	    default:
106472b676d7Smrg	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
106572b676d7Smrg	       break;
106672b676d7Smrg	 }
106772b676d7Smrg      }
106872b676d7Smrg   }
106972b676d7Smrg
107072b676d7Smrg   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
107172b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
107272b676d7Smrg         SiS_Pr->SiS_SysFlags |= SF_760LFB;
107372b676d7Smrg      }
107472b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
107572b676d7Smrg         SiS_Pr->SiS_SysFlags |= SF_760UMA;
107672b676d7Smrg      }
107772b676d7Smrg   }
107872b676d7Smrg}
107972b676d7Smrg
108072b676d7Smrg/*********************************************/
108172b676d7Smrg/*         HELPER: Init PCI & Engines        */
108272b676d7Smrg/*********************************************/
108372b676d7Smrg
108472b676d7Smrgstatic void
108572b676d7SmrgSiSInitPCIetc(struct SiS_Private *SiS_Pr)
108672b676d7Smrg{
108772b676d7Smrg   switch(SiS_Pr->ChipType) {
108872b676d7Smrg#ifdef SIS300
108972b676d7Smrg   case SIS_300:
109072b676d7Smrg   case SIS_540:
109172b676d7Smrg   case SIS_630:
109272b676d7Smrg   case SIS_730:
109372b676d7Smrg      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
109472b676d7Smrg       *     - RELOCATED VGA IO ENABLED (0x20)
109572b676d7Smrg       *     - MMIO ENABLED (0x01)
109672b676d7Smrg       * Leave other bits untouched.
109772b676d7Smrg       */
109872b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
109972b676d7Smrg      /*  - Enable 2D (0x40)
110072b676d7Smrg       *  - Enable 3D (0x02)
110172b676d7Smrg       *  - Enable 3D Vertex command fetch (0x10) ?
110272b676d7Smrg       *  - Enable 3D command parser (0x08) ?
110372b676d7Smrg       */
110472b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
110572b676d7Smrg      break;
110672b676d7Smrg#endif
110772b676d7Smrg#ifdef SIS315H
110872b676d7Smrg   case SIS_315H:
110972b676d7Smrg   case SIS_315:
111072b676d7Smrg   case SIS_315PRO:
111172b676d7Smrg   case SIS_650:
111272b676d7Smrg   case SIS_740:
111372b676d7Smrg   case SIS_330:
111472b676d7Smrg   case SIS_661:
111572b676d7Smrg   case SIS_741:
111672b676d7Smrg   case SIS_660:
111772b676d7Smrg   case SIS_760:
111872b676d7Smrg   case SIS_761:
111972b676d7Smrg   case SIS_340:
112072b676d7Smrg   case XGI_40:
112172b676d7Smrg      /* See above */
112272b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
112372b676d7Smrg      /*  - Enable 3D G/L transformation engine (0x80)
112472b676d7Smrg       *  - Enable 2D (0x40)
112572b676d7Smrg       *  - Enable 3D vertex command fetch (0x10)
112672b676d7Smrg       *  - Enable 3D command parser (0x08)
112772b676d7Smrg       *  - Enable 3D (0x02)
112872b676d7Smrg       */
112972b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
113072b676d7Smrg      break;
113172b676d7Smrg   case XGI_20:
113272b676d7Smrg   case SIS_550:
113372b676d7Smrg      /* See above */
113472b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
113572b676d7Smrg      /* No 3D engine ! */
113672b676d7Smrg      /*  - Enable 2D (0x40)
113772b676d7Smrg       *  - disable 3D
113872b676d7Smrg       */
113972b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
114072b676d7Smrg      break;
114172b676d7Smrg#endif
114272b676d7Smrg   default:
114372b676d7Smrg      break;
114472b676d7Smrg   }
114572b676d7Smrg}
114672b676d7Smrg
114772b676d7Smrg/*********************************************/
114872b676d7Smrg/*             HELPER: SetLVDSetc            */
114972b676d7Smrg/*********************************************/
115072b676d7Smrg
115172b676d7Smrg#ifdef SIS_LINUX_KERNEL
115272b676d7Smrgstatic
115372b676d7Smrg#endif
115472b676d7Smrgvoid
115572b676d7SmrgSiSSetLVDSetc(struct SiS_Private *SiS_Pr)
115672b676d7Smrg{
115772b676d7Smrg   unsigned short temp;
115872b676d7Smrg
115972b676d7Smrg   SiS_Pr->SiS_IF_DEF_LVDS = 0;
116072b676d7Smrg   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
116172b676d7Smrg   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
116272b676d7Smrg   SiS_Pr->SiS_IF_DEF_CONEX = 0;
116372b676d7Smrg
116472b676d7Smrg   SiS_Pr->SiS_ChrontelInit = 0;
116572b676d7Smrg
116672b676d7Smrg   if(SiS_Pr->ChipType == XGI_20) return;
116772b676d7Smrg
116872b676d7Smrg   /* Check for SiS30x first */
116972b676d7Smrg   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
117072b676d7Smrg   if((temp == 1) || (temp == 2)) return;
117172b676d7Smrg
117272b676d7Smrg   switch(SiS_Pr->ChipType) {
117372b676d7Smrg#ifdef SIS300
117472b676d7Smrg   case SIS_540:
117572b676d7Smrg   case SIS_630:
117672b676d7Smrg   case SIS_730:
117772b676d7Smrg	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
117872b676d7Smrg	if((temp >= 2) && (temp <= 5))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
117972b676d7Smrg	if(temp == 3)			SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
118072b676d7Smrg	if((temp == 4) || (temp == 5)) {
118172b676d7Smrg		/* Save power status (and error check) - UNUSED */
118272b676d7Smrg		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
118372b676d7Smrg		SiS_Pr->SiS_IF_DEF_CH70xx = 1;
118472b676d7Smrg	}
118572b676d7Smrg	break;
118672b676d7Smrg#endif
118772b676d7Smrg#ifdef SIS315H
118872b676d7Smrg   case SIS_550:
118972b676d7Smrg   case SIS_650:
119072b676d7Smrg   case SIS_740:
119172b676d7Smrg   case SIS_330:
119272b676d7Smrg	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
119372b676d7Smrg	if((temp >= 2) && (temp <= 3))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
119472b676d7Smrg	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
119572b676d7Smrg	break;
119672b676d7Smrg   case SIS_661:
119772b676d7Smrg   case SIS_741:
119872b676d7Smrg   case SIS_660:
119972b676d7Smrg   case SIS_760:
120072b676d7Smrg   case SIS_761:
120172b676d7Smrg   case SIS_340:
120272b676d7Smrg   case XGI_20:
120372b676d7Smrg   case XGI_40:
120472b676d7Smrg	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
120572b676d7Smrg	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
120672b676d7Smrg	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
120772b676d7Smrg	if(temp == 4)			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
120872b676d7Smrg	break;
120972b676d7Smrg#endif
121072b676d7Smrg   default:
121172b676d7Smrg	break;
121272b676d7Smrg   }
121372b676d7Smrg}
121472b676d7Smrg
121572b676d7Smrg/*********************************************/
121672b676d7Smrg/*          HELPER: Enable DSTN/FSTN         */
121772b676d7Smrg/*********************************************/
121872b676d7Smrg
121972b676d7Smrgvoid
122072b676d7SmrgSiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
122172b676d7Smrg{
122272b676d7Smrg   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
122372b676d7Smrg}
122472b676d7Smrg
122572b676d7Smrgvoid
122672b676d7SmrgSiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
122772b676d7Smrg{
122872b676d7Smrg   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
122972b676d7Smrg}
123072b676d7Smrg
123172b676d7Smrg/*********************************************/
123272b676d7Smrg/*            HELPER: Get modeflag           */
123372b676d7Smrg/*********************************************/
123472b676d7Smrg
123572b676d7Smrgunsigned short
123672b676d7SmrgSiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
123772b676d7Smrg		unsigned short ModeIdIndex)
123872b676d7Smrg{
123972b676d7Smrg   if(SiS_Pr->UseCustomMode) {
124072b676d7Smrg      return SiS_Pr->CModeFlag;
124172b676d7Smrg   } else if(ModeNo <= 0x13) {
124272b676d7Smrg      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
124372b676d7Smrg   } else {
124472b676d7Smrg      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
124572b676d7Smrg   }
124672b676d7Smrg}
124772b676d7Smrg
124872b676d7Smrg/*********************************************/
124972b676d7Smrg/*        HELPER: Determine ROM usage        */
125072b676d7Smrg/*********************************************/
125172b676d7Smrg
125272b676d7SmrgBOOLEAN
125372b676d7SmrgSiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
125472b676d7Smrg{
125572b676d7Smrg   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
125672b676d7Smrg   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
125772b676d7Smrg
125872b676d7Smrg   if(SiS_Pr->ChipType >= XGI_20) {
125972b676d7Smrg      /* XGI ROMs don't qualify */
126072b676d7Smrg      return FALSE;
126172b676d7Smrg   } else if(SiS_Pr->ChipType >= SIS_761) {
126272b676d7Smrg      /* I very much assume 761, 340 and newer will use new layout */
126372b676d7Smrg      return TRUE;
126472b676d7Smrg   } else if(SiS_Pr->ChipType >= SIS_661) {
126572b676d7Smrg      if((ROMAddr[0x1a] == 'N') &&
126672b676d7Smrg	 (ROMAddr[0x1b] == 'e') &&
126772b676d7Smrg	 (ROMAddr[0x1c] == 'w') &&
126872b676d7Smrg	 (ROMAddr[0x1d] == 'V')) {
126972b676d7Smrg	 return TRUE;
127072b676d7Smrg      }
127172b676d7Smrg      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
127272b676d7Smrg      if(romversoffs) {
127372b676d7Smrg	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
127472b676d7Smrg	    romvmaj = ROMAddr[romversoffs] - '0';
127572b676d7Smrg	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
127672b676d7Smrg	 }
127772b676d7Smrg      }
127872b676d7Smrg      if((romvmaj != 0) || (romvmin >= 92)) {
127972b676d7Smrg	 return TRUE;
128072b676d7Smrg      }
128172b676d7Smrg   } else if(IS_SIS650740) {
128272b676d7Smrg      if((ROMAddr[0x1a] == 'N') &&
128372b676d7Smrg	 (ROMAddr[0x1b] == 'e') &&
128472b676d7Smrg	 (ROMAddr[0x1c] == 'w') &&
128572b676d7Smrg	 (ROMAddr[0x1d] == 'V')) {
128672b676d7Smrg	 return TRUE;
128772b676d7Smrg      }
128872b676d7Smrg   }
128972b676d7Smrg   return FALSE;
129072b676d7Smrg}
129172b676d7Smrg
129272b676d7Smrgstatic void
129372b676d7SmrgSiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
129472b676d7Smrg{
129572b676d7Smrg   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
129672b676d7Smrg   unsigned short romptr = 0;
129772b676d7Smrg
129872b676d7Smrg   SiS_Pr->SiS_UseROM = FALSE;
129972b676d7Smrg   SiS_Pr->SiS_ROMNew = FALSE;
130072b676d7Smrg   SiS_Pr->SiS_PWDOffset = 0;
130172b676d7Smrg
130272b676d7Smrg   if(SiS_Pr->ChipType >= XGI_20) return;
130372b676d7Smrg
130472b676d7Smrg   if((ROMAddr) && (SiS_Pr->UseROM)) {
130572b676d7Smrg      if(SiS_Pr->ChipType == SIS_300) {
130672b676d7Smrg	 /* 300: We check if the code starts below 0x220 by
130772b676d7Smrg	  * checking the jmp instruction at the beginning
130872b676d7Smrg	  * of the BIOS image.
130972b676d7Smrg	  */
131072b676d7Smrg	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
131172b676d7Smrg	    SiS_Pr->SiS_UseROM = TRUE;
131272b676d7Smrg      } else if(SiS_Pr->ChipType < SIS_315H) {
131372b676d7Smrg	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
131472b676d7Smrg	  * the others do as well
131572b676d7Smrg	  */
131672b676d7Smrg	 SiS_Pr->SiS_UseROM = TRUE;
131772b676d7Smrg      } else {
131872b676d7Smrg	 /* 315/330 series stick to the standard(s) */
131972b676d7Smrg	 SiS_Pr->SiS_UseROM = TRUE;
132072b676d7Smrg	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
132172b676d7Smrg	    SiS_Pr->SiS_EMIOffset = 14;
132272b676d7Smrg	    SiS_Pr->SiS_PWDOffset = 17;
132372b676d7Smrg	    SiS_Pr->SiS661LCD2TableSize = 36;
132472b676d7Smrg	    /* Find out about LCD data table entry size */
132572b676d7Smrg	    if((romptr = SISGETROMW(0x0102))) {
132672b676d7Smrg	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
132772b676d7Smrg		  SiS_Pr->SiS661LCD2TableSize = 32;
132872b676d7Smrg	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
132972b676d7Smrg		  SiS_Pr->SiS661LCD2TableSize = 34;
133072b676d7Smrg	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)	   /* 0.94, 2.05.00+ */
133172b676d7Smrg		  SiS_Pr->SiS661LCD2TableSize = 36;
133272b676d7Smrg	       else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
133372b676d7Smrg		 	(ROMAddr[0x6F] & 0x01) ) {		   /* 2.03.00 - <2.05.00 */
133472b676d7Smrg		  SiS_Pr->SiS661LCD2TableSize = 38;		   /* UMC data layout abandoned at 2.05.00 */
133572b676d7Smrg		  SiS_Pr->SiS_EMIOffset = 16;
133672b676d7Smrg		  SiS_Pr->SiS_PWDOffset = 19;
133772b676d7Smrg	       }
133872b676d7Smrg	    }
133972b676d7Smrg	 }
134072b676d7Smrg      }
134172b676d7Smrg   }
134272b676d7Smrg}
134372b676d7Smrg
134472b676d7Smrg/*********************************************/
134572b676d7Smrg/*        HELPER: SET SEGMENT REGISTERS      */
134672b676d7Smrg/*********************************************/
134772b676d7Smrg
134872b676d7Smrgstatic void
134972b676d7SmrgSiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
135072b676d7Smrg{
135172b676d7Smrg   unsigned short temp;
135272b676d7Smrg
135372b676d7Smrg   value &= 0x00ff;
135472b676d7Smrg   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
135572b676d7Smrg   temp |= (value >> 4);
135672b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
135772b676d7Smrg   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
135872b676d7Smrg   temp |= (value & 0x0f);
135972b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
136072b676d7Smrg}
136172b676d7Smrg
136272b676d7Smrgstatic void
136372b676d7SmrgSiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
136472b676d7Smrg{
136572b676d7Smrg   unsigned short temp;
136672b676d7Smrg
136772b676d7Smrg   value &= 0x00ff;
136872b676d7Smrg   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
136972b676d7Smrg   temp |= (value & 0xf0);
137072b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
137172b676d7Smrg   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
137272b676d7Smrg   temp |= (value << 4);
137372b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
137472b676d7Smrg}
137572b676d7Smrg
137672b676d7Smrgstatic void
137772b676d7SmrgSiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
137872b676d7Smrg{
137972b676d7Smrg   SiS_SetSegRegLower(SiS_Pr, value);
138072b676d7Smrg   SiS_SetSegRegUpper(SiS_Pr, value);
138172b676d7Smrg}
138272b676d7Smrg
138372b676d7Smrgstatic void
138472b676d7SmrgSiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
138572b676d7Smrg{
138672b676d7Smrg   SiS_SetSegmentReg(SiS_Pr, 0);
138772b676d7Smrg}
138872b676d7Smrg
138972b676d7Smrgstatic void
139072b676d7SmrgSiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
139172b676d7Smrg{
139272b676d7Smrg   unsigned short temp = value >> 8;
139372b676d7Smrg
139472b676d7Smrg   temp &= 0x07;
139572b676d7Smrg   temp |= (temp << 4);
139672b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
139772b676d7Smrg   SiS_SetSegmentReg(SiS_Pr, value);
139872b676d7Smrg}
139972b676d7Smrg
140072b676d7Smrgstatic void
140172b676d7SmrgSiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
140272b676d7Smrg{
140372b676d7Smrg   SiS_SetSegmentRegOver(SiS_Pr, 0);
140472b676d7Smrg}
140572b676d7Smrg
140672b676d7Smrgstatic void
140772b676d7SmrgSiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
140872b676d7Smrg{
140972b676d7Smrg   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
141072b676d7Smrg      SiS_ResetSegmentReg(SiS_Pr);
141172b676d7Smrg      SiS_ResetSegmentRegOver(SiS_Pr);
141272b676d7Smrg   }
141372b676d7Smrg}
141472b676d7Smrg
141572b676d7Smrg/*********************************************/
141672b676d7Smrg/*             HELPER: GetVBType             */
141772b676d7Smrg/*********************************************/
141872b676d7Smrg
141972b676d7Smrg#ifdef SIS_LINUX_KERNEL
142072b676d7Smrgstatic
142172b676d7Smrg#endif
142272b676d7Smrgvoid
142372b676d7SmrgSiS_GetVBType(struct SiS_Private *SiS_Pr)
142472b676d7Smrg{
142572b676d7Smrg   unsigned short flag = 0, rev = 0, nolcd = 0;
142672b676d7Smrg   unsigned short p4_0f, p4_25, p4_27;
142772b676d7Smrg
142872b676d7Smrg   SiS_Pr->SiS_VBType = 0;
142972b676d7Smrg
143072b676d7Smrg   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
143172b676d7Smrg      return;
143272b676d7Smrg
143372b676d7Smrg   if(SiS_Pr->ChipType == XGI_20)
143472b676d7Smrg      return;
143572b676d7Smrg
143672b676d7Smrg   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
143772b676d7Smrg
143872b676d7Smrg   if(flag > 3)
143972b676d7Smrg      return;
144072b676d7Smrg
144172b676d7Smrg   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
144272b676d7Smrg
144372b676d7Smrg   if(flag >= 2) {
144472b676d7Smrg      SiS_Pr->SiS_VBType = VB_SIS302B;
144572b676d7Smrg   } else if(flag == 1) {
144672b676d7Smrg      if(rev >= 0xC0) {
144772b676d7Smrg	 SiS_Pr->SiS_VBType = VB_SIS301C;
144872b676d7Smrg      } else if(rev >= 0xB0) {
144972b676d7Smrg	 SiS_Pr->SiS_VBType = VB_SIS301B;
145072b676d7Smrg	 /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
145172b676d7Smrg	 nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
145272b676d7Smrg	 if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
145372b676d7Smrg      } else {
145472b676d7Smrg	 SiS_Pr->SiS_VBType = VB_SIS301;
145572b676d7Smrg      }
145672b676d7Smrg   }
145772b676d7Smrg   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
145872b676d7Smrg      if(rev >= 0xE0) {
145972b676d7Smrg	 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
146072b676d7Smrg	 if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
146172b676d7Smrg	 else 	 	  SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
146272b676d7Smrg      } else if(rev >= 0xD0) {
146372b676d7Smrg	 SiS_Pr->SiS_VBType = VB_SIS301LV;
146472b676d7Smrg      }
146572b676d7Smrg   }
146672b676d7Smrg   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
146772b676d7Smrg      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
146872b676d7Smrg      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
146972b676d7Smrg      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
147072b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
147172b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
147272b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
147372b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
147472b676d7Smrg         SiS_Pr->SiS_VBType |= VB_UMC;
147572b676d7Smrg      }
147672b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
147772b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
147872b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
147972b676d7Smrg   }
148072b676d7Smrg}
148172b676d7Smrg
148272b676d7Smrg/*********************************************/
148372b676d7Smrg/*           HELPER: Check RAM size          */
148472b676d7Smrg/*********************************************/
148572b676d7Smrg
148672b676d7Smrg#ifdef SIS_LINUX_KERNEL
148772b676d7Smrgstatic BOOLEAN
148872b676d7SmrgSiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
148972b676d7Smrg		unsigned short ModeIdIndex)
149072b676d7Smrg{
149172b676d7Smrg   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
149272b676d7Smrg   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
149372b676d7Smrg   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
149472b676d7Smrg
149572b676d7Smrg   if(!AdapterMemSize) return TRUE;
149672b676d7Smrg
149772b676d7Smrg   if(AdapterMemSize < memorysize) return FALSE;
149872b676d7Smrg   return TRUE;
149972b676d7Smrg}
150072b676d7Smrg#endif
150172b676d7Smrg
150272b676d7Smrg/*********************************************/
150372b676d7Smrg/*           HELPER: Get DRAM type           */
150472b676d7Smrg/*********************************************/
150572b676d7Smrg
150672b676d7Smrg#ifdef SIS315H
150772b676d7Smrgstatic unsigned char
150872b676d7SmrgSiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
150972b676d7Smrg{
151072b676d7Smrg   unsigned char data;
151172b676d7Smrg
151272b676d7Smrg   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
151372b676d7Smrg      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
151472b676d7Smrg   } else {
151572b676d7Smrg      if(SiS_Pr->ChipType >= XGI_20) {
151672b676d7Smrg         /* Do I need this? SR17 seems to be zero anyway... */
151772b676d7Smrg	 data = 0;
151872b676d7Smrg      } else if(SiS_Pr->ChipType >= SIS_340) {
151972b676d7Smrg	 /* TODO */
152072b676d7Smrg	 data = 0;
152172b676d7Smrg      } if(SiS_Pr->ChipType >= SIS_661) {
152272b676d7Smrg	 if(SiS_Pr->SiS_ROMNew) {
152372b676d7Smrg	    data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
152472b676d7Smrg	 } else {
152572b676d7Smrg	    data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
152672b676d7Smrg	 }
152772b676d7Smrg      } else if(IS_SIS550650740) {
152872b676d7Smrg	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
152972b676d7Smrg      } else {	/* 315, 330 */
153072b676d7Smrg	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
153172b676d7Smrg	 if(SiS_Pr->ChipType == SIS_330) {
153272b676d7Smrg	    if(data > 1) {
153372b676d7Smrg	       switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
153472b676d7Smrg	       case 0x00: data = 1; break;
153572b676d7Smrg	       case 0x10: data = 3; break;
153672b676d7Smrg	       case 0x20: data = 3; break;
153772b676d7Smrg	       case 0x30: data = 2; break;
153872b676d7Smrg	       }
153972b676d7Smrg	    } else {
154072b676d7Smrg	       data = 0;
154172b676d7Smrg	    }
154272b676d7Smrg	 }
154372b676d7Smrg      }
154472b676d7Smrg   }
154572b676d7Smrg
154672b676d7Smrg   return data;
154772b676d7Smrg}
154872b676d7Smrg
154972b676d7Smrgstatic unsigned short
155072b676d7SmrgSiS_GetMCLK(struct SiS_Private *SiS_Pr)
155172b676d7Smrg{
155272b676d7Smrg   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
155372b676d7Smrg   unsigned short index;
155472b676d7Smrg
155572b676d7Smrg   index = SiS_Get310DRAMType(SiS_Pr);
155672b676d7Smrg   if(SiS_Pr->ChipType >= SIS_661) {
155772b676d7Smrg      if(SiS_Pr->SiS_ROMNew) {
155872b676d7Smrg	 return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
155972b676d7Smrg      }
156072b676d7Smrg      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
156172b676d7Smrg   } else if(index >= 4) {
156272b676d7Smrg      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
156372b676d7Smrg   } else {
156472b676d7Smrg      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
156572b676d7Smrg   }
156672b676d7Smrg}
156772b676d7Smrg#endif
156872b676d7Smrg
156972b676d7Smrg/*********************************************/
157072b676d7Smrg/*           HELPER: ClearBuffer             */
157172b676d7Smrg/*********************************************/
157272b676d7Smrg
157372b676d7Smrg#ifdef SIS_LINUX_KERNEL
157472b676d7Smrgstatic void
157572b676d7SmrgSiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
157672b676d7Smrg{
157772b676d7Smrg   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
157872b676d7Smrg   unsigned int   memsize = SiS_Pr->VideoMemorySize;
157972b676d7Smrg   unsigned short SISIOMEMTYPE *pBuffer;
158072b676d7Smrg   int i;
158172b676d7Smrg
158272b676d7Smrg   if(!memaddr || !memsize) return;
158372b676d7Smrg
158472b676d7Smrg   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
158572b676d7Smrg      if(ModeNo > 0x13) {
158672b676d7Smrg	 SiS_SetMemory(memaddr, memsize, 0);
158772b676d7Smrg      } else {
158872b676d7Smrg	 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
158972b676d7Smrg	 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
159072b676d7Smrg      }
159172b676d7Smrg   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
159272b676d7Smrg      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
159372b676d7Smrg      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
159472b676d7Smrg   } else {
159572b676d7Smrg      SiS_SetMemory(memaddr, 0x8000, 0);
159672b676d7Smrg   }
159772b676d7Smrg}
159872b676d7Smrg#endif
159972b676d7Smrg
160072b676d7Smrg/*********************************************/
160172b676d7Smrg/*           HELPER: SearchModeID            */
160272b676d7Smrg/*********************************************/
160372b676d7Smrg
160472b676d7SmrgBOOLEAN
160572b676d7SmrgSiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
160672b676d7Smrg		unsigned short *ModeIdIndex)
160772b676d7Smrg{
160872b676d7Smrg   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
160972b676d7Smrg
161072b676d7Smrg   if((*ModeNo) <= 0x13) {
161172b676d7Smrg
161272b676d7Smrg      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
161372b676d7Smrg
161472b676d7Smrg      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
161572b676d7Smrg	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
161672b676d7Smrg	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
161772b676d7Smrg      }
161872b676d7Smrg
161972b676d7Smrg      if((*ModeNo) == 0x07) {
162072b676d7Smrg	  if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
162172b676d7Smrg	  /* else 350 lines */
162272b676d7Smrg      }
162372b676d7Smrg      if((*ModeNo) <= 0x03) {
162472b676d7Smrg	 if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
162572b676d7Smrg	 if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
162672b676d7Smrg	 /* else 350 lines  */
162772b676d7Smrg      }
162872b676d7Smrg      /* else 200 lines  */
162972b676d7Smrg
163072b676d7Smrg   } else {
163172b676d7Smrg
163272b676d7Smrg      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
163372b676d7Smrg	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
163472b676d7Smrg	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
163572b676d7Smrg      }
163672b676d7Smrg
163772b676d7Smrg   }
163872b676d7Smrg   return TRUE;
163972b676d7Smrg}
164072b676d7Smrg
164172b676d7Smrg/*********************************************/
164272b676d7Smrg/*            HELPER: GetModePtr             */
164372b676d7Smrg/*********************************************/
164472b676d7Smrg
164572b676d7Smrgunsigned short
164672b676d7SmrgSiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
164772b676d7Smrg{
164872b676d7Smrg   unsigned short index;
164972b676d7Smrg
165072b676d7Smrg   if(ModeNo <= 0x13) {
165172b676d7Smrg      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
165272b676d7Smrg   } else {
165372b676d7Smrg      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
165472b676d7Smrg      else index = 0x0F;
165572b676d7Smrg   }
165672b676d7Smrg   return index;
165772b676d7Smrg}
165872b676d7Smrg
165972b676d7Smrg/*********************************************/
166072b676d7Smrg/*         HELPERS: Get some indices         */
166172b676d7Smrg/*********************************************/
166272b676d7Smrg
166372b676d7Smrgunsigned short
166472b676d7SmrgSiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
166572b676d7Smrg{
166672b676d7Smrg   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
166772b676d7Smrg      if(UseWide == 1) {
166872b676d7Smrg         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
166972b676d7Smrg      } else {
167072b676d7Smrg         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
167172b676d7Smrg      }
167272b676d7Smrg   } else {
167372b676d7Smrg      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
167472b676d7Smrg   }
167572b676d7Smrg}
167672b676d7Smrg
167772b676d7Smrgunsigned short
167872b676d7SmrgSiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
167972b676d7Smrg{
168072b676d7Smrg   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
168172b676d7Smrg      if(UseWide == 1) {
168272b676d7Smrg         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
168372b676d7Smrg      } else {
168472b676d7Smrg         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
168572b676d7Smrg      }
168672b676d7Smrg   } else {
168772b676d7Smrg      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
168872b676d7Smrg   }
168972b676d7Smrg}
169072b676d7Smrg
169172b676d7Smrg/*********************************************/
169272b676d7Smrg/*           HELPER: LowModeTests            */
169372b676d7Smrg/*********************************************/
169472b676d7Smrg
169572b676d7Smrgstatic BOOLEAN
169672b676d7SmrgSiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
169772b676d7Smrg{
169872b676d7Smrg   unsigned short temp, temp1, temp2;
169972b676d7Smrg
170072b676d7Smrg   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
170172b676d7Smrg      return TRUE;
170272b676d7Smrg   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
170372b676d7Smrg   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
170472b676d7Smrg   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
170572b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
170672b676d7Smrg   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
170772b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
170872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
170972b676d7Smrg   if((SiS_Pr->ChipType >= SIS_315H) ||
171072b676d7Smrg      (SiS_Pr->ChipType == SIS_300)) {
171172b676d7Smrg      if(temp2 == 0x55) return FALSE;
171272b676d7Smrg      else return TRUE;
171372b676d7Smrg   } else {
171472b676d7Smrg      if(temp2 != 0x55) return TRUE;
171572b676d7Smrg      else {
171672b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
171772b676d7Smrg	 return FALSE;
171872b676d7Smrg      }
171972b676d7Smrg   }
172072b676d7Smrg}
172172b676d7Smrg
172272b676d7Smrgstatic void
172372b676d7SmrgSiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
172472b676d7Smrg{
172572b676d7Smrg   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
172672b676d7Smrg      SiS_Pr->SiS_SetFlag |= LowModeTests;
172772b676d7Smrg   }
172872b676d7Smrg}
172972b676d7Smrg
173072b676d7Smrg/*********************************************/
173172b676d7Smrg/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
173272b676d7Smrg/*********************************************/
173372b676d7Smrg
173472b676d7Smrgstatic void
173572b676d7SmrgSiS_OpenCRTC(struct SiS_Private *SiS_Pr)
173672b676d7Smrg{
173772b676d7Smrg   if(IS_SIS650) {
173872b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
173972b676d7Smrg      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
174072b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
174172b676d7Smrg   } else if(IS_SIS661741660760) {
174272b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
174372b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
174472b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
174572b676d7Smrg      if(!SiS_Pr->SiS_ROMNew) {
174672b676d7Smrg	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
174772b676d7Smrg      }
174872b676d7Smrg   }
174972b676d7Smrg}
175072b676d7Smrg
175172b676d7Smrgstatic void
175272b676d7SmrgSiS_CloseCRTC(struct SiS_Private *SiS_Pr)
175372b676d7Smrg{
175472b676d7Smrg#if 0 /* This locks some CRTC registers. We don't want that. */
175572b676d7Smrg   unsigned short temp1 = 0, temp2 = 0;
175672b676d7Smrg
175772b676d7Smrg   if(IS_SIS661741660760) {
175872b676d7Smrg      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
175972b676d7Smrg         temp1 = 0xa0; temp2 = 0x08;
176072b676d7Smrg      }
176172b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
176272b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
176372b676d7Smrg   }
176472b676d7Smrg#endif
176572b676d7Smrg}
176672b676d7Smrg
176772b676d7Smrgstatic void
176872b676d7SmrgSiS_HandleCRT1(struct SiS_Private *SiS_Pr)
176972b676d7Smrg{
177072b676d7Smrg   /* Enable CRT1 gating */
177172b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
177272b676d7Smrg#if 0
177372b676d7Smrg   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
177472b676d7Smrg      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
177572b676d7Smrg         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
177672b676d7Smrg         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
177772b676d7Smrg      }
177872b676d7Smrg   }
177972b676d7Smrg#endif
178072b676d7Smrg}
178172b676d7Smrg
178272b676d7Smrg/*********************************************/
178372b676d7Smrg/*           HELPER: GetColorDepth           */
178472b676d7Smrg/*********************************************/
178572b676d7Smrg
178672b676d7Smrgunsigned short
178772b676d7SmrgSiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
178872b676d7Smrg		unsigned short ModeIdIndex)
178972b676d7Smrg{
179072b676d7Smrg   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
179172b676d7Smrg   unsigned short modeflag;
179272b676d7Smrg   short index;
179372b676d7Smrg
179472b676d7Smrg   /* Do NOT check UseCustomMode, will skrew up FIFO */
179572b676d7Smrg   if(ModeNo == 0xfe) {
179672b676d7Smrg      modeflag = SiS_Pr->CModeFlag;
179772b676d7Smrg   } else if(ModeNo <= 0x13) {
179872b676d7Smrg      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
179972b676d7Smrg   } else {
180072b676d7Smrg      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
180172b676d7Smrg   }
180272b676d7Smrg
180372b676d7Smrg   index = (modeflag & ModeTypeMask) - ModeEGA;
180472b676d7Smrg   if(index < 0) index = 0;
180572b676d7Smrg   return ColorDepth[index];
180672b676d7Smrg}
180772b676d7Smrg
180872b676d7Smrg/*********************************************/
180972b676d7Smrg/*             HELPER: GetOffset             */
181072b676d7Smrg/*********************************************/
181172b676d7Smrg
181272b676d7Smrgunsigned short
181372b676d7SmrgSiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
181472b676d7Smrg		unsigned short ModeIdIndex, unsigned short RRTI)
181572b676d7Smrg{
181672b676d7Smrg   unsigned short xres, temp, colordepth, infoflag;
181772b676d7Smrg
181872b676d7Smrg   if(SiS_Pr->UseCustomMode) {
181972b676d7Smrg      infoflag = SiS_Pr->CInfoFlag;
182072b676d7Smrg      xres = SiS_Pr->CHDisplay;
182172b676d7Smrg   } else {
182272b676d7Smrg      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
182372b676d7Smrg      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
182472b676d7Smrg   }
182572b676d7Smrg
182672b676d7Smrg   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
182772b676d7Smrg
182872b676d7Smrg   temp = xres / 16;
182972b676d7Smrg   if(infoflag & InterlaceMode) temp <<= 1;
183072b676d7Smrg   temp *= colordepth;
183172b676d7Smrg   if(xres % 16) temp += (colordepth >> 1);
183272b676d7Smrg
183372b676d7Smrg   return temp;
183472b676d7Smrg}
183572b676d7Smrg
183672b676d7Smrg/*********************************************/
183772b676d7Smrg/*                   SEQ                     */
183872b676d7Smrg/*********************************************/
183972b676d7Smrg
184072b676d7Smrgstatic void
184172b676d7SmrgSiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
184272b676d7Smrg{
184372b676d7Smrg   unsigned char SRdata;
184472b676d7Smrg   int i;
184572b676d7Smrg
184672b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
184772b676d7Smrg
184872b676d7Smrg   /* or "display off"  */
184972b676d7Smrg   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
185072b676d7Smrg
185172b676d7Smrg   /* determine whether to force x8 dotclock */
185272b676d7Smrg   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
185372b676d7Smrg
185472b676d7Smrg      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
185572b676d7Smrg         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
185672b676d7Smrg      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
185772b676d7Smrg
185872b676d7Smrg   }
185972b676d7Smrg
186072b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
186172b676d7Smrg
186272b676d7Smrg   for(i = 2; i <= 4; i++) {
186372b676d7Smrg      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
186472b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
186572b676d7Smrg   }
186672b676d7Smrg}
186772b676d7Smrg
186872b676d7Smrg/*********************************************/
186972b676d7Smrg/*                  MISC                     */
187072b676d7Smrg/*********************************************/
187172b676d7Smrg
187272b676d7Smrgstatic void
187372b676d7SmrgSiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
187472b676d7Smrg{
187572b676d7Smrg   unsigned char Miscdata;
187672b676d7Smrg
187772b676d7Smrg   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
187872b676d7Smrg
187972b676d7Smrg   if(SiS_Pr->ChipType < SIS_661) {
188072b676d7Smrg      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
188172b676d7Smrg	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
188272b676d7Smrg	   Miscdata |= 0x0C;
188372b676d7Smrg	 }
188472b676d7Smrg      }
188572b676d7Smrg   }
188672b676d7Smrg
188772b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
188872b676d7Smrg}
188972b676d7Smrg
189072b676d7Smrg/*********************************************/
189172b676d7Smrg/*                  CRTC                     */
189272b676d7Smrg/*********************************************/
189372b676d7Smrg
189472b676d7Smrgstatic void
189572b676d7SmrgSiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
189672b676d7Smrg{
189772b676d7Smrg   unsigned char  CRTCdata;
189872b676d7Smrg   unsigned short i;
189972b676d7Smrg
190072b676d7Smrg   /* Unlock CRTC */
190172b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
190272b676d7Smrg
190372b676d7Smrg   for(i = 0; i <= 0x18; i++) {
190472b676d7Smrg      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
190572b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
190672b676d7Smrg   }
190772b676d7Smrg
190872b676d7Smrg   if(SiS_Pr->ChipType >= SIS_661) {
190972b676d7Smrg      SiS_OpenCRTC(SiS_Pr);
191072b676d7Smrg      for(i = 0x13; i <= 0x14; i++) {
191172b676d7Smrg	 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
191272b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
191372b676d7Smrg      }
191472b676d7Smrg   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
191572b676d7Smrg	        (SiS_Pr->ChipType == SIS_730) )  &&
191672b676d7Smrg	      (SiS_Pr->ChipRevision >= 0x30) ) {
191772b676d7Smrg      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
191872b676d7Smrg	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
191972b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
192072b676d7Smrg	 }
192172b676d7Smrg      }
192272b676d7Smrg   }
192372b676d7Smrg}
192472b676d7Smrg
192572b676d7Smrg/*********************************************/
192672b676d7Smrg/*                   ATT                     */
192772b676d7Smrg/*********************************************/
192872b676d7Smrg
192972b676d7Smrgstatic void
193072b676d7SmrgSiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
193172b676d7Smrg{
193272b676d7Smrg   unsigned char  ARdata;
193372b676d7Smrg   unsigned short i;
193472b676d7Smrg
193572b676d7Smrg   for(i = 0; i <= 0x13; i++) {
193672b676d7Smrg      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
193772b676d7Smrg
193872b676d7Smrg      if(i == 0x13) {
193972b676d7Smrg	 /* Pixel shift. If screen on LCD or TV is shifted left or right,
194072b676d7Smrg	  * this might be the cause.
194172b676d7Smrg	  */
194272b676d7Smrg	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
194372b676d7Smrg	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
194472b676d7Smrg	 }
194572b676d7Smrg	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
194672b676d7Smrg	    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
194772b676d7Smrg	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
194872b676d7Smrg		  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
194972b676d7Smrg	       }
195072b676d7Smrg	    }
195172b676d7Smrg	 }
195272b676d7Smrg	 if(SiS_Pr->ChipType >= SIS_661) {
195372b676d7Smrg	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
195472b676d7Smrg	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
195572b676d7Smrg	    }
195672b676d7Smrg	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
195772b676d7Smrg	    if(SiS_Pr->ChipType >= SIS_315H) {
195872b676d7Smrg	       if(IS_SIS550650740660) {
195972b676d7Smrg		  /* 315, 330 don't do this */
196072b676d7Smrg		  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
196172b676d7Smrg		     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
196272b676d7Smrg		  } else {
196372b676d7Smrg		     ARdata = 0;
196472b676d7Smrg		  }
196572b676d7Smrg	       }
196672b676d7Smrg	    } else {
196772b676d7Smrg	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
196872b676d7Smrg	    }
196972b676d7Smrg	 }
197072b676d7Smrg      }
197172b676d7Smrg      SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
197272b676d7Smrg      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);	/* set index  */
197372b676d7Smrg      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);	/* set data   */
197472b676d7Smrg   }
197572b676d7Smrg
197672b676d7Smrg   SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
197772b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);	/* set index  */
197872b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);	/* set data   */
197972b676d7Smrg
198072b676d7Smrg   SiS_GetRegByte(SiS_Pr->SiS_P3da);
198172b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);	/* Enable Attribute  */
198272b676d7Smrg   SiS_GetRegByte(SiS_Pr->SiS_P3da);
198372b676d7Smrg}
198472b676d7Smrg
198572b676d7Smrg/*********************************************/
198672b676d7Smrg/*                   GRC                     */
198772b676d7Smrg/*********************************************/
198872b676d7Smrg
198972b676d7Smrgstatic void
199072b676d7SmrgSiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
199172b676d7Smrg{
199272b676d7Smrg   unsigned char  GRdata;
199372b676d7Smrg   unsigned short i;
199472b676d7Smrg
199572b676d7Smrg   for(i = 0; i <= 0x08; i++) {
199672b676d7Smrg      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
199772b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
199872b676d7Smrg   }
199972b676d7Smrg
200072b676d7Smrg   if(SiS_Pr->SiS_ModeType > ModeVGA) {
200172b676d7Smrg      /* 256 color disable */
200272b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
200372b676d7Smrg   }
200472b676d7Smrg}
200572b676d7Smrg
200672b676d7Smrg/*********************************************/
200772b676d7Smrg/*          CLEAR EXTENDED REGISTERS         */
200872b676d7Smrg/*********************************************/
200972b676d7Smrg
201072b676d7Smrgstatic void
201172b676d7SmrgSiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
201272b676d7Smrg{
201372b676d7Smrg   unsigned short i;
201472b676d7Smrg
201572b676d7Smrg   for(i = 0x0A; i <= 0x0E; i++) {
201672b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
201772b676d7Smrg   }
201872b676d7Smrg
201972b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
202072b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
202172b676d7Smrg      if(ModeNo <= 0x13) {
202272b676d7Smrg	 if(ModeNo == 0x06 || ModeNo >= 0x0e) {
202372b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
202472b676d7Smrg	 }
202572b676d7Smrg      }
202672b676d7Smrg   }
202772b676d7Smrg}
202872b676d7Smrg
202972b676d7Smrg/*********************************************/
203072b676d7Smrg/*                 RESET VCLK                */
203172b676d7Smrg/*********************************************/
203272b676d7Smrg
203372b676d7Smrgstatic void
203472b676d7SmrgSiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
203572b676d7Smrg{
203672b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
203772b676d7Smrg      if(SiS_Pr->ChipType < SIS_661) {
203872b676d7Smrg	 if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
203972b676d7Smrg      }
204072b676d7Smrg   } else {
204172b676d7Smrg      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
204272b676d7Smrg	 (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
204372b676d7Smrg	 return;
204472b676d7Smrg      }
204572b676d7Smrg   }
204672b676d7Smrg
204772b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
204872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
204972b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
205072b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
205172b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
205272b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
205372b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
205472b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
205572b676d7Smrg}
205672b676d7Smrg
205772b676d7Smrg/*********************************************/
205872b676d7Smrg/*                  SYNC                     */
205972b676d7Smrg/*********************************************/
206072b676d7Smrg
206172b676d7Smrgstatic void
206272b676d7SmrgSiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
206372b676d7Smrg{
206472b676d7Smrg   unsigned short sync;
206572b676d7Smrg
206672b676d7Smrg   if(SiS_Pr->UseCustomMode) {
206772b676d7Smrg      sync = SiS_Pr->CInfoFlag >> 8;
206872b676d7Smrg   } else {
206972b676d7Smrg      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
207072b676d7Smrg   }
207172b676d7Smrg
207272b676d7Smrg   sync &= 0xC0;
207372b676d7Smrg   sync |= 0x2f;
207472b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
207572b676d7Smrg}
207672b676d7Smrg
207772b676d7Smrg/*********************************************/
207872b676d7Smrg/*                  CRTC/2                   */
207972b676d7Smrg/*********************************************/
208072b676d7Smrg
208172b676d7Smrgstatic void
208272b676d7SmrgSiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
208372b676d7Smrg		unsigned short ModeIdIndex, unsigned short RRTI)
208472b676d7Smrg{
208572b676d7Smrg   unsigned short temp, i, j, modeflag;
208672b676d7Smrg   unsigned char  *crt1data = NULL;
208772b676d7Smrg
208872b676d7Smrg   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
208972b676d7Smrg
209072b676d7Smrg   if(SiS_Pr->UseCustomMode) {
209172b676d7Smrg
209272b676d7Smrg      crt1data = &SiS_Pr->CCRT1CRTC[0];
209372b676d7Smrg
209472b676d7Smrg   } else {
209572b676d7Smrg
209672b676d7Smrg      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
209772b676d7Smrg
209872b676d7Smrg      /* Alternate for 1600x1200 LCDA */
209972b676d7Smrg      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
210072b676d7Smrg
210172b676d7Smrg      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
210272b676d7Smrg
210372b676d7Smrg   }
210472b676d7Smrg
210572b676d7Smrg   /* unlock cr0-7 */
210672b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
210772b676d7Smrg
210872b676d7Smrg   for(i = 0, j = 0; i <= 7; i++, j++) {
210972b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
211072b676d7Smrg   }
211172b676d7Smrg   for(j = 0x10; i <= 10; i++, j++) {
211272b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
211372b676d7Smrg   }
211472b676d7Smrg   for(j = 0x15; i <= 12; i++, j++) {
211572b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
211672b676d7Smrg   }
211772b676d7Smrg   for(j = 0x0A; i <= 15; i++, j++) {
211872b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
211972b676d7Smrg   }
212072b676d7Smrg
212172b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
212272b676d7Smrg
212372b676d7Smrg   temp = (crt1data[16] & 0x01) << 5;
212472b676d7Smrg   if(modeflag & DoubleScanMode) temp |= 0x80;
212572b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
212672b676d7Smrg
212772b676d7Smrg   if(SiS_Pr->SiS_ModeType > ModeVGA) {
212872b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
212972b676d7Smrg   }
213072b676d7Smrg
213172b676d7Smrg#ifdef SIS315H
213272b676d7Smrg   if(SiS_Pr->ChipType == XGI_20) {
213372b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
213472b676d7Smrg      if(!(temp = crt1data[5] & 0x1f)) {
213572b676d7Smrg         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
213672b676d7Smrg      }
213772b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
213872b676d7Smrg      temp = (crt1data[16] >> 5) + 3;
213972b676d7Smrg      if(temp > 7) temp -= 7;
214072b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
214172b676d7Smrg   }
214272b676d7Smrg#endif
214372b676d7Smrg}
214472b676d7Smrg
214572b676d7Smrg/*********************************************/
214672b676d7Smrg/*               OFFSET & PITCH              */
214772b676d7Smrg/*********************************************/
214872b676d7Smrg/*  (partly overruled by SetPitch() in XF86) */
214972b676d7Smrg/*********************************************/
215072b676d7Smrg
215172b676d7Smrgstatic void
215272b676d7SmrgSiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
215372b676d7Smrg		unsigned short ModeIdIndex, unsigned short RRTI)
215472b676d7Smrg{
215572b676d7Smrg   unsigned short temp, DisplayUnit, infoflag;
215672b676d7Smrg
215772b676d7Smrg   if(SiS_Pr->UseCustomMode) {
215872b676d7Smrg      infoflag = SiS_Pr->CInfoFlag;
215972b676d7Smrg   } else {
216072b676d7Smrg      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
216172b676d7Smrg   }
216272b676d7Smrg
216372b676d7Smrg   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
216472b676d7Smrg
216572b676d7Smrg   temp = (DisplayUnit >> 8) & 0x0f;
216672b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
216772b676d7Smrg
216872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
216972b676d7Smrg
217072b676d7Smrg   if(infoflag & InterlaceMode) DisplayUnit >>= 1;
217172b676d7Smrg
217272b676d7Smrg   DisplayUnit <<= 5;
217372b676d7Smrg   temp = (DisplayUnit >> 8) + 1;
217472b676d7Smrg   if(DisplayUnit & 0xff) temp++;
217572b676d7Smrg   if(SiS_Pr->ChipType == XGI_20) {
217672b676d7Smrg      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
217772b676d7Smrg   }
217872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
217972b676d7Smrg}
218072b676d7Smrg
218172b676d7Smrg/*********************************************/
218272b676d7Smrg/*                  VCLK                     */
218372b676d7Smrg/*********************************************/
218472b676d7Smrg
218572b676d7Smrgstatic void
218672b676d7SmrgSiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
218772b676d7Smrg		unsigned short ModeIdIndex, unsigned short RRTI)
218872b676d7Smrg{
218972b676d7Smrg   unsigned short index = 0, clka, clkb;
219072b676d7Smrg
219172b676d7Smrg   if(SiS_Pr->UseCustomMode) {
219272b676d7Smrg      clka = SiS_Pr->CSR2B;
219372b676d7Smrg      clkb = SiS_Pr->CSR2C;
219472b676d7Smrg   } else {
219572b676d7Smrg      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
219672b676d7Smrg      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
219772b676d7Smrg	 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
219872b676d7Smrg	 /* Alternate for 1600x1200 LCDA */
219972b676d7Smrg	 if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
220072b676d7Smrg	 clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
220172b676d7Smrg	 clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
220272b676d7Smrg      } else {
220372b676d7Smrg	 clka = SiS_Pr->SiS_VCLKData[index].SR2B;
220472b676d7Smrg	 clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
220572b676d7Smrg      }
220672b676d7Smrg   }
220772b676d7Smrg
220872b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
220972b676d7Smrg
221072b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
221172b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
221272b676d7Smrg
221372b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
221472b676d7Smrg#ifdef SIS315H
221572b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
221672b676d7Smrg      if(SiS_Pr->ChipType == XGI_20) {
221772b676d7Smrg         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
221872b676d7Smrg	 if(mf & HalfDCLK) {
221972b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
222072b676d7Smrg	    clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
222172b676d7Smrg	    clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
222272b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
222372b676d7Smrg	 }
222472b676d7Smrg      }
222572b676d7Smrg#endif
222672b676d7Smrg   } else {
222772b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
222872b676d7Smrg   }
222972b676d7Smrg}
223072b676d7Smrg
223172b676d7Smrg/*********************************************/
223272b676d7Smrg/*                  FIFO                     */
223372b676d7Smrg/*********************************************/
223472b676d7Smrg
223572b676d7Smrg#ifdef SIS300
223672b676d7Smrgvoid
223772b676d7SmrgSiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
223872b676d7Smrg		unsigned short *idx2)
223972b676d7Smrg{
224072b676d7Smrg   unsigned short temp1, temp2;
224172b676d7Smrg   static const unsigned char ThTiming[8] = {
224272b676d7Smrg		1, 2, 2, 3, 0, 1, 1, 2
224372b676d7Smrg   };
224472b676d7Smrg
224572b676d7Smrg   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
224672b676d7Smrg   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
224772b676d7Smrg   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
224872b676d7Smrg   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
224972b676d7Smrg   (*idx1) <<= 1;
225072b676d7Smrg}
225172b676d7Smrg
225272b676d7Smrgstatic unsigned short
225372b676d7SmrgSiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
225472b676d7Smrg{
225572b676d7Smrg   static const unsigned char ThLowA[8 * 3] = {
225672b676d7Smrg		61, 3,52, 5,68, 7,100,11,
225772b676d7Smrg		43, 3,42, 5,54, 7, 78,11,
225872b676d7Smrg		34, 3,37, 5,47, 7, 67,11
225972b676d7Smrg   };
226072b676d7Smrg
226172b676d7Smrg   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
226272b676d7Smrg}
226372b676d7Smrg
226472b676d7Smrgunsigned short
226572b676d7SmrgSiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
226672b676d7Smrg{
226772b676d7Smrg   static const unsigned char ThLowB[8 * 3] = {
226872b676d7Smrg		81, 4,72, 6,88, 8,120,12,
226972b676d7Smrg		55, 4,54, 6,66, 8, 90,12,
227072b676d7Smrg		42, 4,45, 6,55, 8, 75,12
227172b676d7Smrg   };
227272b676d7Smrg
227372b676d7Smrg   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
227472b676d7Smrg}
227572b676d7Smrg
227672b676d7Smrgstatic unsigned short
227772b676d7SmrgSiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
227872b676d7Smrg		unsigned short colordepth, unsigned short key)
227972b676d7Smrg{
228072b676d7Smrg   unsigned short idx1, idx2;
228172b676d7Smrg   unsigned int   longtemp = VCLK * colordepth;
228272b676d7Smrg
228372b676d7Smrg   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
228472b676d7Smrg
228572b676d7Smrg   if(key == 0) {
228672b676d7Smrg      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
228772b676d7Smrg   } else {
228872b676d7Smrg      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
228972b676d7Smrg   }
229072b676d7Smrg   idx1 = longtemp % (MCLK * 16);
229172b676d7Smrg   longtemp /= (MCLK * 16);
229272b676d7Smrg   if(idx1) longtemp++;
229372b676d7Smrg   return (unsigned short)longtemp;
229472b676d7Smrg}
229572b676d7Smrg
229672b676d7Smrgstatic unsigned short
229772b676d7SmrgSiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
229872b676d7Smrg		unsigned short colordepth, unsigned short MCLK)
229972b676d7Smrg{
230072b676d7Smrg   unsigned short temp1, temp2;
230172b676d7Smrg
230272b676d7Smrg   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
230372b676d7Smrg   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
230472b676d7Smrg   if(temp1 < 4) temp1 = 4;
230572b676d7Smrg   temp1 -= 4;
230672b676d7Smrg   if(temp2 < temp1) temp2 = temp1;
230772b676d7Smrg   return temp2;
230872b676d7Smrg}
230972b676d7Smrg
231072b676d7Smrgstatic void
231172b676d7SmrgSiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
231272b676d7Smrg		unsigned short RefreshRateTableIndex)
231372b676d7Smrg{
231472b676d7Smrg   unsigned short ThresholdLow = 0;
231572b676d7Smrg   unsigned short temp, index, VCLK, MCLK, colorth;
231672b676d7Smrg   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
231772b676d7Smrg
231872b676d7Smrg   if(ModeNo > 0x13) {
231972b676d7Smrg
232072b676d7Smrg      /* Get VCLK  */
232172b676d7Smrg      if(SiS_Pr->UseCustomMode) {
232272b676d7Smrg	 VCLK = SiS_Pr->CSRClock;
232372b676d7Smrg      } else {
232472b676d7Smrg	 index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
232572b676d7Smrg	 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
232672b676d7Smrg      }
232772b676d7Smrg
232872b676d7Smrg      /* Get half colordepth */
232972b676d7Smrg      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
233072b676d7Smrg
233172b676d7Smrg      /* Get MCLK  */
233272b676d7Smrg      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
233372b676d7Smrg      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
233472b676d7Smrg
233572b676d7Smrg      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
233672b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
233772b676d7Smrg
233872b676d7Smrg      do {
233972b676d7Smrg	 ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
234072b676d7Smrg	 if(ThresholdLow < 0x13) break;
234172b676d7Smrg	 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
234272b676d7Smrg	 ThresholdLow = 0x13;
234372b676d7Smrg	 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
234472b676d7Smrg	 if(!temp) break;
234572b676d7Smrg	 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
234672b676d7Smrg      } while(0);
234772b676d7Smrg
234872b676d7Smrg   } else ThresholdLow = 2;
234972b676d7Smrg
235072b676d7Smrg   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
235172b676d7Smrg   temp = (ThresholdLow << 4) | 0x0f;
235272b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
235372b676d7Smrg
235472b676d7Smrg   temp = (ThresholdLow & 0x10) << 1;
235572b676d7Smrg   if(ModeNo > 0x13) temp |= 0x40;
235672b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
235772b676d7Smrg
235872b676d7Smrg   /* What is this? */
235972b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
236072b676d7Smrg
236172b676d7Smrg   /* Write CRT/CPU threshold high */
236272b676d7Smrg   temp = ThresholdLow + 3;
236372b676d7Smrg   if(temp > 0x0f) temp = 0x0f;
236472b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
236572b676d7Smrg}
236672b676d7Smrg
236772b676d7Smrgunsigned short
236872b676d7SmrgSiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
236972b676d7Smrg{
237072b676d7Smrg   static const unsigned char LatencyFactor[] = {
237172b676d7Smrg		97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
237272b676d7Smrg		 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
237372b676d7Smrg		97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
237472b676d7Smrg		 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
237572b676d7Smrg		80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
237672b676d7Smrg		 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
237772b676d7Smrg		86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
237872b676d7Smrg		 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
237972b676d7Smrg   };
238072b676d7Smrg   static const unsigned char LatencyFactor730[] = {
238172b676d7Smrg		 69, 63, 61,
238272b676d7Smrg		 86, 79, 77,
238372b676d7Smrg		103, 96, 94,
238472b676d7Smrg		120,113,111,
238572b676d7Smrg		137,130,128
238672b676d7Smrg   };
238772b676d7Smrg
238872b676d7Smrg   if(SiS_Pr->ChipType == SIS_730) {
238972b676d7Smrg      return (unsigned short)LatencyFactor730[index];
239072b676d7Smrg   } else {
239172b676d7Smrg      return (unsigned short)LatencyFactor[index];
239272b676d7Smrg   }
239372b676d7Smrg}
239472b676d7Smrg
239572b676d7Smrgstatic unsigned short
239672b676d7SmrgSiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
239772b676d7Smrg{
239872b676d7Smrg   unsigned short index;
239972b676d7Smrg
240072b676d7Smrg   if(SiS_Pr->ChipType == SIS_730) {
240172b676d7Smrg      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
240272b676d7Smrg   } else {
240372b676d7Smrg      index = (key & 0xe0) >> 5;
240472b676d7Smrg      if(key & 0x10)    index +=  6;
240572b676d7Smrg      if(!(key & 0x01)) index += 24;
240672b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
240772b676d7Smrg   }
240872b676d7Smrg   return SiS_GetLatencyFactor630(SiS_Pr, index);
240972b676d7Smrg}
241072b676d7Smrg
241172b676d7Smrgstatic void
241272b676d7SmrgSiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
241372b676d7Smrg                    unsigned short RefreshRateTableIndex)
241472b676d7Smrg{
241572b676d7Smrg   unsigned short  ThresholdLow = 0;
241672b676d7Smrg   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
241772b676d7Smrg   unsigned int    templ, datal;
241872b676d7Smrg   const unsigned char *queuedata = NULL;
241972b676d7Smrg   static const unsigned char FQBQData[21] = {
242072b676d7Smrg		0x01,0x21,0x41,0x61,0x81,
242172b676d7Smrg		0x31,0x51,0x71,0x91,0xb1,
242272b676d7Smrg		0x00,0x20,0x40,0x60,0x80,
242372b676d7Smrg		0x30,0x50,0x70,0x90,0xb0,
242472b676d7Smrg		0xff
242572b676d7Smrg   };
242672b676d7Smrg   static const unsigned char FQBQData730[16] = {
242772b676d7Smrg		0x34,0x74,0xb4,
242872b676d7Smrg		0x23,0x63,0xa3,
242972b676d7Smrg		0x12,0x52,0x92,
243072b676d7Smrg		0x01,0x41,0x81,
243172b676d7Smrg		0x00,0x40,0x80,
243272b676d7Smrg		0xff
243372b676d7Smrg   };
243472b676d7Smrg   static const unsigned short colortharray[6] = {
243572b676d7Smrg		1, 1, 2, 2, 3, 4
243672b676d7Smrg   };
243772b676d7Smrg
243872b676d7Smrg   i = 0;
243972b676d7Smrg
244072b676d7Smrg   if(ModeNo > 0x13) {
244172b676d7Smrg
244272b676d7Smrg      /* Get VCLK  */
244372b676d7Smrg      if(SiS_Pr->UseCustomMode) {
244472b676d7Smrg	 VCLK = SiS_Pr->CSRClock;
244572b676d7Smrg      } else {
244672b676d7Smrg	 data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
244772b676d7Smrg	 VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
244872b676d7Smrg      }
244972b676d7Smrg
245072b676d7Smrg      /* Get MCLK * 16 */
245172b676d7Smrg      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
245272b676d7Smrg      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
245372b676d7Smrg
245472b676d7Smrg      /* Get half colordepth */
245572b676d7Smrg      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
245672b676d7Smrg
245772b676d7Smrg      if(SiS_Pr->ChipType == SIS_730) {
245872b676d7Smrg	 queuedata = &FQBQData730[0];
245972b676d7Smrg      } else {
246072b676d7Smrg	 queuedata = &FQBQData[0];
246172b676d7Smrg      }
246272b676d7Smrg
246372b676d7Smrg      do {
246472b676d7Smrg	 templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
246572b676d7Smrg
246672b676d7Smrg	 datal = templ % MCLK16;
246772b676d7Smrg	 templ = (templ / MCLK16) + 1;
246872b676d7Smrg	 if(datal) templ++;
246972b676d7Smrg
247072b676d7Smrg	 if(templ > 0x13) {
247172b676d7Smrg	    if(queuedata[i + 1] == 0xFF) {
247272b676d7Smrg	       ThresholdLow = 0x13;
247372b676d7Smrg	       break;
247472b676d7Smrg	    }
247572b676d7Smrg	    i++;
247672b676d7Smrg	 } else {
247772b676d7Smrg	    ThresholdLow = templ;
247872b676d7Smrg	    break;
247972b676d7Smrg	 }
248072b676d7Smrg      } while(queuedata[i] != 0xFF);
248172b676d7Smrg
248272b676d7Smrg   } else {
248372b676d7Smrg
248472b676d7Smrg      if(SiS_Pr->ChipType != SIS_730) i = 9;
248572b676d7Smrg      ThresholdLow = 0x02;
248672b676d7Smrg
248772b676d7Smrg   }
248872b676d7Smrg
248972b676d7Smrg   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
249072b676d7Smrg   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
249172b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
249272b676d7Smrg
249372b676d7Smrg   data = (ThresholdLow & 0x10) << 1;
249472b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
249572b676d7Smrg
249672b676d7Smrg   /* What is this? */
249772b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
249872b676d7Smrg
249972b676d7Smrg   /* Write CRT/CPU threshold high (gap = 3) */
250072b676d7Smrg   data = ThresholdLow + 3;
250172b676d7Smrg   if(data > 0x0f) data = 0x0f;
250272b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
250372b676d7Smrg
250472b676d7Smrg  /* Write foreground and background queue */
250572b676d7Smrg#ifdef SIS_LINUX_KERNEL
250672b676d7Smrg   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
250772b676d7Smrg#else
250872b676d7Smrg   templ = pciReadLong(0x00000000, 0x50);
250972b676d7Smrg#endif
251072b676d7Smrg
251172b676d7Smrg   if(SiS_Pr->ChipType == SIS_730) {
251272b676d7Smrg
251372b676d7Smrg      templ &= 0xfffff9ff;
251472b676d7Smrg      templ |= ((queuedata[i] & 0xc0) << 3);
251572b676d7Smrg
251672b676d7Smrg   } else {
251772b676d7Smrg
251872b676d7Smrg      templ &= 0xf0ffffff;
251972b676d7Smrg      if( (ModeNo <= 0x13) &&
252072b676d7Smrg          (SiS_Pr->ChipType == SIS_630) &&
252172b676d7Smrg	  (SiS_Pr->ChipRevision >= 0x30) ) {
252272b676d7Smrg	 templ |= 0x0b000000;
252372b676d7Smrg      } else {
252472b676d7Smrg         templ |= ((queuedata[i] & 0xf0) << 20);
252572b676d7Smrg      }
252672b676d7Smrg
252772b676d7Smrg   }
252872b676d7Smrg
252972b676d7Smrg#ifdef SIS_LINUX_KERNEL
253072b676d7Smrg   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
253172b676d7Smrg   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
253272b676d7Smrg#else
253372b676d7Smrg   pciWriteLong(0x00000000, 0x50, templ);
253472b676d7Smrg   templ = pciReadLong(0x00000000, 0xA0);
253572b676d7Smrg#endif
253672b676d7Smrg
253772b676d7Smrg   /* GUI grant timer (PCI config 0xA3) */
253872b676d7Smrg   if(SiS_Pr->ChipType == SIS_730) {
253972b676d7Smrg
254072b676d7Smrg      templ &= 0x00ffffff;
254172b676d7Smrg      datal = queuedata[i] << 8;
254272b676d7Smrg      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
254372b676d7Smrg
254472b676d7Smrg   } else {
254572b676d7Smrg
254672b676d7Smrg      templ &= 0xf0ffffff;
254772b676d7Smrg      templ |= ((queuedata[i] & 0x0f) << 24);
254872b676d7Smrg
254972b676d7Smrg   }
255072b676d7Smrg
255172b676d7Smrg#ifdef SIS_LINUX_KERNEL
255272b676d7Smrg   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
255372b676d7Smrg#else
255472b676d7Smrg   pciWriteLong(0x00000000, 0xA0, templ);
255572b676d7Smrg#endif
255672b676d7Smrg}
255772b676d7Smrg#endif /* SIS300 */
255872b676d7Smrg
255972b676d7Smrg#ifdef SIS315H
256072b676d7Smrgstatic void
256172b676d7SmrgSiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
256272b676d7Smrg{
256372b676d7Smrg   unsigned short modeflag;
256472b676d7Smrg
256572b676d7Smrg   /* disable auto-threshold */
256672b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
256772b676d7Smrg
256872b676d7Smrg   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
256972b676d7Smrg
257072b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
257172b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
257272b676d7Smrg   if(ModeNo > 0x13) {
257372b676d7Smrg      if(SiS_Pr->ChipType >= XGI_20) {
257472b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
257572b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
257672b676d7Smrg      } else if(SiS_Pr->ChipType >= SIS_661) {
257772b676d7Smrg	 if(!(modeflag & HalfDCLK)) {
257872b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
257972b676d7Smrg	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
258072b676d7Smrg	 }
258172b676d7Smrg      } else {
258272b676d7Smrg	 if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
258372b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
258472b676d7Smrg	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
258572b676d7Smrg	 }
258672b676d7Smrg      }
258772b676d7Smrg   }
258872b676d7Smrg}
258972b676d7Smrg#endif
259072b676d7Smrg
259172b676d7Smrg/*********************************************/
259272b676d7Smrg/*              MODE REGISTERS               */
259372b676d7Smrg/*********************************************/
259472b676d7Smrg
259572b676d7Smrgstatic void
259672b676d7SmrgSiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
259772b676d7Smrg		unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
259872b676d7Smrg{
259972b676d7Smrg   unsigned short data = 0, VCLK = 0, index = 0;
260072b676d7Smrg
260172b676d7Smrg   if(ModeNo > 0x13) {
260272b676d7Smrg      if(SiS_Pr->UseCustomMode) {
260372b676d7Smrg         VCLK = SiS_Pr->CSRClock;
260472b676d7Smrg      } else {
260572b676d7Smrg         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
260672b676d7Smrg         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
260772b676d7Smrg      }
260872b676d7Smrg   }
260972b676d7Smrg
261072b676d7Smrg   if(SiS_Pr->ChipType < SIS_315H) {
261172b676d7Smrg#ifdef SIS300
261272b676d7Smrg      if(VCLK > 150) data |= 0x80;
261372b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
261472b676d7Smrg
261572b676d7Smrg      data = 0x00;
261672b676d7Smrg      if(VCLK >= 150) data |= 0x08;
261772b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
261872b676d7Smrg#endif
261972b676d7Smrg   } else if(SiS_Pr->ChipType < XGI_20) {
262072b676d7Smrg#ifdef SIS315H
262172b676d7Smrg      if(VCLK >= 166) data |= 0x0c;
262272b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
262372b676d7Smrg
262472b676d7Smrg      if(VCLK >= 166) {
262572b676d7Smrg         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
262672b676d7Smrg      }
262772b676d7Smrg#endif
262872b676d7Smrg   } else {
262972b676d7Smrg#ifdef SIS315H
263072b676d7Smrg      if(VCLK >= 200) data |= 0x0c;
263172b676d7Smrg      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
263272b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
263372b676d7Smrg      if(SiS_Pr->ChipType != XGI_20) {
263472b676d7Smrg         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
263572b676d7Smrg	 if(VCLK < 200) data |= 0x10;
263672b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
263772b676d7Smrg      }
263872b676d7Smrg#endif
263972b676d7Smrg   }
264072b676d7Smrg
264172b676d7Smrg   /* DAC speed */
264272b676d7Smrg   if(SiS_Pr->ChipType >= SIS_661) {
264372b676d7Smrg
264472b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
264572b676d7Smrg
264672b676d7Smrg   } else {
264772b676d7Smrg
264872b676d7Smrg      data = 0x03;
264972b676d7Smrg      if(VCLK >= 260)      data = 0x00;
265072b676d7Smrg      else if(VCLK >= 160) data = 0x01;
265172b676d7Smrg      else if(VCLK >= 135) data = 0x02;
265272b676d7Smrg
265372b676d7Smrg      if(SiS_Pr->ChipType == SIS_540) {
265472b676d7Smrg         if((VCLK == 203) || (VCLK < 234)) data = 0x02;
265572b676d7Smrg      }
265672b676d7Smrg
265772b676d7Smrg      if(SiS_Pr->ChipType < SIS_315H) {
265872b676d7Smrg         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
265972b676d7Smrg      } else {
266072b676d7Smrg         if(SiS_Pr->ChipType > SIS_315PRO) {
266172b676d7Smrg            if(ModeNo > 0x13) data &= 0xfc;
266272b676d7Smrg         }
266372b676d7Smrg         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
266472b676d7Smrg      }
266572b676d7Smrg
266672b676d7Smrg   }
266772b676d7Smrg}
266872b676d7Smrg
266972b676d7Smrgstatic void
267072b676d7SmrgSiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
267172b676d7Smrg		unsigned short ModeIdIndex, unsigned short RRTI)
267272b676d7Smrg{
267372b676d7Smrg   unsigned short data, infoflag = 0, modeflag, resindex;
267472b676d7Smrg#ifdef SIS315H
267572b676d7Smrg   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
267672b676d7Smrg   unsigned short data2, data3;
267772b676d7Smrg#endif
267872b676d7Smrg
267972b676d7Smrg   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
268072b676d7Smrg
268172b676d7Smrg   if(SiS_Pr->UseCustomMode) {
268272b676d7Smrg      infoflag = SiS_Pr->CInfoFlag;
268372b676d7Smrg   } else {
268472b676d7Smrg      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
268572b676d7Smrg      if(ModeNo > 0x13) {
268672b676d7Smrg	 infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
268772b676d7Smrg      }
268872b676d7Smrg   }
268972b676d7Smrg
269072b676d7Smrg   /* Disable DPMS */
269172b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
269272b676d7Smrg
269372b676d7Smrg   data = 0;
269472b676d7Smrg   if(ModeNo > 0x13) {
269572b676d7Smrg      if(SiS_Pr->SiS_ModeType > ModeEGA) {
269672b676d7Smrg         data |= 0x02;
269772b676d7Smrg         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
269872b676d7Smrg      }
269972b676d7Smrg      if(infoflag & InterlaceMode) data |= 0x20;
270072b676d7Smrg   }
270172b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
270272b676d7Smrg
270372b676d7Smrg   if(SiS_Pr->ChipType != SIS_300) {
270472b676d7Smrg      data = 0;
270572b676d7Smrg      if(infoflag & InterlaceMode) {
270672b676d7Smrg	 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
270772b676d7Smrg	 int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
270872b676d7Smrg		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
270972b676d7Smrg	 int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
271072b676d7Smrg		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
271172b676d7Smrg	 data = hrs - (hto >> 1) + 3;
271272b676d7Smrg      }
271372b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
271472b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
271572b676d7Smrg   }
271672b676d7Smrg
271772b676d7Smrg   if(modeflag & HalfDCLK) {
271872b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
271972b676d7Smrg   }
272072b676d7Smrg
272172b676d7Smrg   data = 0;
272272b676d7Smrg   if(modeflag & LineCompareOff) data = 0x08;
272372b676d7Smrg   if(SiS_Pr->ChipType == SIS_300) {
272472b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
272572b676d7Smrg   } else {
272672b676d7Smrg      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
272772b676d7Smrg      if(SiS_Pr->SiS_ModeType == ModeEGA) {
272872b676d7Smrg	 if(ModeNo > 0x13) {
272972b676d7Smrg	    data |= 0x40;
273072b676d7Smrg	 }
273172b676d7Smrg      }
273272b676d7Smrg      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
273372b676d7Smrg   }
273472b676d7Smrg
273572b676d7Smrg#ifdef SIS315H
273672b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
273772b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
273872b676d7Smrg   }
273972b676d7Smrg
274072b676d7Smrg   if(SiS_Pr->ChipType == SIS_315PRO) {
274172b676d7Smrg
274272b676d7Smrg      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
274372b676d7Smrg      if(SiS_Pr->SiS_ModeType == ModeText) {
274472b676d7Smrg	 data &= 0xc7;
274572b676d7Smrg      } else {
274672b676d7Smrg	 data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
274772b676d7Smrg	 if(infoflag & InterlaceMode) data2 >>= 1;
274872b676d7Smrg	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
274972b676d7Smrg	 if(data3) data2 /= data3;
275072b676d7Smrg	 if(data2 >= 0x50) {
275172b676d7Smrg	    data &= 0x0f;
275272b676d7Smrg	    data |= 0x50;
275372b676d7Smrg	 }
275472b676d7Smrg      }
275572b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
275672b676d7Smrg
275772b676d7Smrg   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
275872b676d7Smrg
275972b676d7Smrg      data = SiS_Get310DRAMType(SiS_Pr);
276072b676d7Smrg      if(SiS_Pr->ChipType == SIS_330) {
276172b676d7Smrg	 data = SiS_Pr->SiS_SR15[(2 * 4) + data];
276272b676d7Smrg      } else {
276372b676d7Smrg	 if(SiS_Pr->SiS_ROMNew)	     data = ROMAddr[0xf6];
276472b676d7Smrg	 else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
276572b676d7Smrg	 else			     data = 0xba;
276672b676d7Smrg      }
276772b676d7Smrg      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
276872b676d7Smrg	 data &= 0xc7;
276972b676d7Smrg      } else {
277072b676d7Smrg	 if(SiS_Pr->UseCustomMode) {
277172b676d7Smrg	    data2 = SiS_Pr->CSRClock;
277272b676d7Smrg	 } else {
277372b676d7Smrg	    data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
277472b676d7Smrg	    data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
277572b676d7Smrg	 }
277672b676d7Smrg
277772b676d7Smrg	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
277872b676d7Smrg	 if(data3) data2 *= data3;
277972b676d7Smrg
278072b676d7Smrg	 data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
278172b676d7Smrg
278272b676d7Smrg	 if(SiS_Pr->ChipType == SIS_330) {
278372b676d7Smrg	    if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
278472b676d7Smrg	       if     (data2 >= 0x19c) data = 0xba;
278572b676d7Smrg	       else if(data2 >= 0x140) data = 0x7a;
278672b676d7Smrg	       else if(data2 >= 0x101) data = 0x3a;
278772b676d7Smrg	       else if(data2 >= 0xf5)  data = 0x32;
278872b676d7Smrg	       else if(data2 >= 0xe2)  data = 0x2a;
278972b676d7Smrg	       else if(data2 >= 0xc4)  data = 0x22;
279072b676d7Smrg	       else if(data2 >= 0xac)  data = 0x1a;
279172b676d7Smrg	       else if(data2 >= 0x9e)  data = 0x12;
279272b676d7Smrg	       else if(data2 >= 0x8e)  data = 0x0a;
279372b676d7Smrg	       else                    data = 0x02;
279472b676d7Smrg	    } else {
279572b676d7Smrg	       if(data2 >= 0x127)      data = 0xba;
279672b676d7Smrg	       else                    data = 0x7a;
279772b676d7Smrg	    }
279872b676d7Smrg	 } else {  /* 76x+LFB */
279972b676d7Smrg	    if     (data2 >= 0x190) data = 0xba;
280072b676d7Smrg	    else if(data2 >= 0xff)  data = 0x7a;
280172b676d7Smrg	    else if(data2 >= 0xd3)  data = 0x3a;
280272b676d7Smrg	    else if(data2 >= 0xa9)  data = 0x1a;
280372b676d7Smrg	    else if(data2 >= 0x93)  data = 0x0a;
280472b676d7Smrg	    else                    data = 0x02;
280572b676d7Smrg	 }
280672b676d7Smrg      }
280772b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
280872b676d7Smrg
280972b676d7Smrg   }
281072b676d7Smrg      /* XGI: Nothing. */
281172b676d7Smrg      /* TODO: Check SiS340 */
281272b676d7Smrg#endif
281372b676d7Smrg
281472b676d7Smrg   data = 0x60;
281572b676d7Smrg   if(SiS_Pr->SiS_ModeType != ModeText) {
281672b676d7Smrg      data ^= 0x60;
281772b676d7Smrg      if(SiS_Pr->SiS_ModeType != ModeEGA) {
281872b676d7Smrg         data ^= 0xA0;
281972b676d7Smrg      }
282072b676d7Smrg   }
282172b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
282272b676d7Smrg
282372b676d7Smrg   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
282472b676d7Smrg
282572b676d7Smrg#ifdef SIS315H
282672b676d7Smrg   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
282772b676d7Smrg       (SiS_Pr->ChipType == XGI_40)) {
282872b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
282972b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
283072b676d7Smrg      } else {
283172b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
283272b676d7Smrg      }
283372b676d7Smrg   } else if(SiS_Pr->ChipType == XGI_20) {
283472b676d7Smrg      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
283572b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
283672b676d7Smrg      } else {
283772b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
283872b676d7Smrg      }
283972b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
284072b676d7Smrg   }
284172b676d7Smrg#endif
284272b676d7Smrg}
284372b676d7Smrg
284472b676d7Smrg#ifdef SIS315H
284572b676d7Smrgstatic void
284672b676d7SmrgSiS_SetupDualChip(struct SiS_Private *SiS_Pr)
284772b676d7Smrg{
284872b676d7Smrg#if 0
284972b676d7Smrg   /* TODO: Find out about IOAddress2 */
285072b676d7Smrg   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
285172b676d7Smrg   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
285272b676d7Smrg   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
285372b676d7Smrg   int i;
285472b676d7Smrg
285572b676d7Smrg   if((SiS_Pr->ChipRevision != 0) ||
285672b676d7Smrg      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
285772b676d7Smrg      return;
285872b676d7Smrg
285972b676d7Smrg   for(i = 0; i <= 4; i++) {					/* SR00 - SR04 */
286072b676d7Smrg      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
286172b676d7Smrg   }
286272b676d7Smrg   for(i = 0; i <= 8; i++) {					/* GR00 - GR08 */
286372b676d7Smrg      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
286472b676d7Smrg   }
286572b676d7Smrg   SiS_SetReg(P2_3c4,0x05,0x86);
286672b676d7Smrg   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));	/* SR06 */
286772b676d7Smrg   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));	/* SR21 */
286872b676d7Smrg   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));	/* MISC */
286972b676d7Smrg   SiS_SetReg(P2_3c4,0x05,0x00);
287072b676d7Smrg#endif
287172b676d7Smrg}
287272b676d7Smrg#endif
287372b676d7Smrg
287472b676d7Smrg/*********************************************/
287572b676d7Smrg/*                 LOAD DAC                  */
287672b676d7Smrg/*********************************************/
287772b676d7Smrg
287872b676d7Smrgstatic void
287972b676d7SmrgSiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
288072b676d7Smrg             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
288172b676d7Smrg{
288272b676d7Smrg   unsigned short d1, d2, d3;
288372b676d7Smrg
288472b676d7Smrg   switch(dl) {
288572b676d7Smrg   case  0: d1 = dh; d2 = ah; d3 = al; break;
288672b676d7Smrg   case  1: d1 = ah; d2 = al; d3 = dh; break;
288772b676d7Smrg   default: d1 = al; d2 = dh; d3 = ah;
288872b676d7Smrg   }
288972b676d7Smrg   SiS_SetRegByte(DACData, (d1 << shiftflag));
289072b676d7Smrg   SiS_SetRegByte(DACData, (d2 << shiftflag));
289172b676d7Smrg   SiS_SetRegByte(DACData, (d3 << shiftflag));
289272b676d7Smrg}
289372b676d7Smrg
289472b676d7Smrgvoid
289572b676d7SmrgSiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
289672b676d7Smrg{
289772b676d7Smrg   unsigned short data, data2, time, i, j, k, m, n, o;
289872b676d7Smrg   unsigned short si, di, bx, sf;
289972b676d7Smrg   SISIOADDRESS DACAddr, DACData;
290072b676d7Smrg   const unsigned char *table = NULL;
290172b676d7Smrg
290272b676d7Smrg   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
290372b676d7Smrg
290472b676d7Smrg   j = time = 64;
290572b676d7Smrg   if(data == 0x00)      table = SiS_MDA_DAC;
290672b676d7Smrg   else if(data == 0x08) table = SiS_CGA_DAC;
290772b676d7Smrg   else if(data == 0x10) table = SiS_EGA_DAC;
290872b676d7Smrg   else if(data == 0x18) {
290972b676d7Smrg      j = 16;
291072b676d7Smrg      time = 256;
291172b676d7Smrg      table = SiS_VGA_DAC;
291272b676d7Smrg   }
291372b676d7Smrg
291472b676d7Smrg   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
291572b676d7Smrg         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
291672b676d7Smrg       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
291772b676d7Smrg       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
291872b676d7Smrg      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
291972b676d7Smrg      DACAddr = SiS_Pr->SiS_P3c8;
292072b676d7Smrg      DACData = SiS_Pr->SiS_P3c9;
292172b676d7Smrg      sf = 0;
292272b676d7Smrg   } else {
292372b676d7Smrg      DACAddr = SiS_Pr->SiS_Part5Port;
292472b676d7Smrg      DACData = SiS_Pr->SiS_Part5Port + 1;
292572b676d7Smrg      sf = 2;
292672b676d7Smrg   }
292772b676d7Smrg
292872b676d7Smrg   SiS_SetRegByte(DACAddr,0x00);
292972b676d7Smrg
293072b676d7Smrg   for(i = 0; i < j; i++) {
293172b676d7Smrg      data = table[i];
293272b676d7Smrg      for(k = 0; k < 3; k++) {
293372b676d7Smrg	data2 = 0;
293472b676d7Smrg	if(data & 0x01) data2 += 0x2A;
293572b676d7Smrg	if(data & 0x02) data2 += 0x15;
293672b676d7Smrg	SiS_SetRegByte(DACData, (data2 << sf));
293772b676d7Smrg	data >>= 2;
293872b676d7Smrg      }
293972b676d7Smrg   }
294072b676d7Smrg
294172b676d7Smrg   if(time == 256) {
294272b676d7Smrg      for(i = 16; i < 32; i++) {
294372b676d7Smrg	 data = table[i] << sf;
294472b676d7Smrg	 for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
294572b676d7Smrg      }
294672b676d7Smrg      si = 32;
294772b676d7Smrg      for(m = 0; m < 9; m++) {
294872b676d7Smrg	 di = si;
294972b676d7Smrg	 bx = si + 4;
295072b676d7Smrg	 for(n = 0; n < 3; n++) {
295172b676d7Smrg	    for(o = 0; o < 5; o++) {
295272b676d7Smrg	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
295372b676d7Smrg	       si++;
295472b676d7Smrg	    }
295572b676d7Smrg	    si -= 2;
295672b676d7Smrg	    for(o = 0; o < 3; o++) {
295772b676d7Smrg	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
295872b676d7Smrg	       si--;
295972b676d7Smrg	    }
296072b676d7Smrg	 }            /* for n < 3 */
296172b676d7Smrg	 si += 5;
296272b676d7Smrg      }               /* for m < 9 */
296372b676d7Smrg   }
296472b676d7Smrg}
296572b676d7Smrg
296672b676d7Smrg/*********************************************/
296772b676d7Smrg/*         SET CRT1 REGISTER GROUP           */
296872b676d7Smrg/*********************************************/
296972b676d7Smrg
297072b676d7Smrgstatic void
297172b676d7SmrgSiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
297272b676d7Smrg{
297372b676d7Smrg   unsigned short StandTableIndex, RefreshRateTableIndex;
297472b676d7Smrg
297572b676d7Smrg   SiS_Pr->SiS_CRT1Mode = ModeNo;
297672b676d7Smrg
297772b676d7Smrg   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
297872b676d7Smrg
297972b676d7Smrg   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
298072b676d7Smrg      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
298172b676d7Smrg         SiS_DisableBridge(SiS_Pr);
298272b676d7Smrg      }
298372b676d7Smrg   }
298472b676d7Smrg
298572b676d7Smrg   SiS_ResetSegmentRegisters(SiS_Pr);
298672b676d7Smrg
298772b676d7Smrg   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
298872b676d7Smrg   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
298972b676d7Smrg   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
299072b676d7Smrg   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
299172b676d7Smrg   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
299272b676d7Smrg   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
299372b676d7Smrg   SiS_ResetCRT1VCLK(SiS_Pr);
299472b676d7Smrg
299572b676d7Smrg   SiS_Pr->SiS_SelectCRT2Rate = 0;
299672b676d7Smrg   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
299772b676d7Smrg
299872b676d7Smrg#ifdef SIS_XORG_XF86
299972b676d7Smrg   xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
300072b676d7Smrg                    SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
300172b676d7Smrg#endif
300272b676d7Smrg
300372b676d7Smrg   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
300472b676d7Smrg      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
300572b676d7Smrg         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
300672b676d7Smrg      }
300772b676d7Smrg   }
300872b676d7Smrg
300972b676d7Smrg   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
301072b676d7Smrg      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
301172b676d7Smrg   }
301272b676d7Smrg
301372b676d7Smrg   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
301472b676d7Smrg
301572b676d7Smrg   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
301672b676d7Smrg      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
301772b676d7Smrg   }
301872b676d7Smrg
301972b676d7Smrg   if(RefreshRateTableIndex != 0xFFFF) {
302072b676d7Smrg      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
302172b676d7Smrg      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
302272b676d7Smrg      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
302372b676d7Smrg      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
302472b676d7Smrg   }
302572b676d7Smrg
302672b676d7Smrg   switch(SiS_Pr->ChipType) {
302772b676d7Smrg#ifdef SIS300
302872b676d7Smrg   case SIS_300:
302972b676d7Smrg      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
303072b676d7Smrg      break;
303172b676d7Smrg   case SIS_540:
303272b676d7Smrg   case SIS_630:
303372b676d7Smrg   case SIS_730:
303472b676d7Smrg      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
303572b676d7Smrg      break;
303672b676d7Smrg#endif
303772b676d7Smrg   default:
303872b676d7Smrg#ifdef SIS315H
303972b676d7Smrg      if(SiS_Pr->ChipType == XGI_20) {
304072b676d7Smrg         unsigned char sr2b = 0, sr2c = 0;
304172b676d7Smrg         switch(ModeNo) {
304272b676d7Smrg	 case 0x00:
304372b676d7Smrg	 case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
304472b676d7Smrg	 case 0x04:
304572b676d7Smrg	 case 0x05:
304672b676d7Smrg	 case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
304772b676d7Smrg	 }
304872b676d7Smrg	 if(sr2b) {
304972b676d7Smrg            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
305072b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
305172b676d7Smrg	    SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
305272b676d7Smrg	 }
305372b676d7Smrg      }
305472b676d7Smrg      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
305572b676d7Smrg#endif
305672b676d7Smrg      break;
305772b676d7Smrg   }
305872b676d7Smrg
305972b676d7Smrg   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
306072b676d7Smrg
306172b676d7Smrg#ifdef SIS315H
306272b676d7Smrg   if(SiS_Pr->ChipType == XGI_40) {
306372b676d7Smrg      SiS_SetupDualChip(SiS_Pr);
306472b676d7Smrg   }
306572b676d7Smrg#endif
306672b676d7Smrg
306772b676d7Smrg   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
306872b676d7Smrg
306972b676d7Smrg#ifdef SIS_LINUX_KERNEL
307072b676d7Smrg   if(SiS_Pr->SiS_flag_clearbuffer) {
307172b676d7Smrg      SiS_ClearBuffer(SiS_Pr, ModeNo);
307272b676d7Smrg   }
307372b676d7Smrg#endif
307472b676d7Smrg
307572b676d7Smrg   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
307672b676d7Smrg      SiS_WaitRetrace1(SiS_Pr);
307772b676d7Smrg      SiS_DisplayOn(SiS_Pr);
307872b676d7Smrg   }
307972b676d7Smrg}
308072b676d7Smrg
308172b676d7Smrg/*********************************************/
308272b676d7Smrg/*       HELPER: VIDEO BRIDGE PROG CLK       */
308372b676d7Smrg/*********************************************/
308472b676d7Smrg
308572b676d7Smrgstatic void
308672b676d7SmrgSiS_InitVB(struct SiS_Private *SiS_Pr)
308772b676d7Smrg{
308872b676d7Smrg   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
308972b676d7Smrg
309072b676d7Smrg   SiS_Pr->Init_P4_0E = 0;
309172b676d7Smrg   if(SiS_Pr->SiS_ROMNew) {
309272b676d7Smrg      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
309372b676d7Smrg   } else if(SiS_Pr->ChipType >= XGI_40) {
309472b676d7Smrg      if(SiS_Pr->SiS_XGIROM) {
309572b676d7Smrg         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
309672b676d7Smrg      }
309772b676d7Smrg   }
309872b676d7Smrg}
309972b676d7Smrg
310072b676d7Smrgstatic void
310172b676d7SmrgSiS_ResetVB(struct SiS_Private *SiS_Pr)
310272b676d7Smrg{
310372b676d7Smrg#ifdef SIS315H
310472b676d7Smrg   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
310572b676d7Smrg   unsigned short temp;
310672b676d7Smrg
310772b676d7Smrg   /* VB programming clock */
310872b676d7Smrg   if(SiS_Pr->SiS_UseROM) {
310972b676d7Smrg      if(SiS_Pr->ChipType < SIS_330) {
311072b676d7Smrg	 temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
311172b676d7Smrg	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
311272b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
311372b676d7Smrg      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
311472b676d7Smrg	 temp = ROMAddr[0x7e] | 0x40;
311572b676d7Smrg	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
311672b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
311772b676d7Smrg      }
311872b676d7Smrg   } else if(SiS_Pr->ChipType >= XGI_40) {
311972b676d7Smrg      temp = 0x40;
312072b676d7Smrg      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
312172b676d7Smrg      /* Can we do this on any chipset? */
312272b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
312372b676d7Smrg   }
312472b676d7Smrg#endif
312572b676d7Smrg}
312672b676d7Smrg
312772b676d7Smrg/*********************************************/
312872b676d7Smrg/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
312972b676d7Smrg/*********************************************/
313072b676d7Smrg
313172b676d7Smrgstatic void
313272b676d7SmrgSiS_StrangeStuff(struct SiS_Private *SiS_Pr)
313372b676d7Smrg{
313472b676d7Smrg   /* SiS65x and XGI set up some sort of "lock mode" for text
313572b676d7Smrg    * which locks CRT2 in some way to CRT1 timing. Disable
313672b676d7Smrg    * this here.
313772b676d7Smrg    */
313872b676d7Smrg#ifdef SIS315H
313972b676d7Smrg   if((IS_SIS651) || (IS_SISM650) ||
314072b676d7Smrg      SiS_Pr->ChipType == SIS_340 ||
314172b676d7Smrg      SiS_Pr->ChipType == XGI_40) {
314272b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
314372b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
314472b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
314572b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
314672b676d7Smrg      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
314772b676d7Smrg   }
314872b676d7Smrg   /* !!! This does not support modes < 0x13 !!! */
314972b676d7Smrg#endif
315072b676d7Smrg}
315172b676d7Smrg
315272b676d7Smrg/*********************************************/
315372b676d7Smrg/*     HELPER: SET AGP TIMING FOR SiS760     */
315472b676d7Smrg/*********************************************/
315572b676d7Smrg
315672b676d7Smrgstatic void
315772b676d7SmrgSiS_Handle760(struct SiS_Private *SiS_Pr)
315872b676d7Smrg{
315972b676d7Smrg#ifdef SIS315H
316072b676d7Smrg   unsigned int somebase;
316172b676d7Smrg   unsigned char temp1, temp2, temp3;
316272b676d7Smrg
316372b676d7Smrg   if( (SiS_Pr->ChipType != SIS_760)                         ||
316472b676d7Smrg       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
316572b676d7Smrg       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
316672b676d7Smrg       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
316772b676d7Smrg      return;
316872b676d7Smrg
316972b676d7Smrg#ifdef SIS_LINUX_KERNEL
317072b676d7Smrg   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
317172b676d7Smrg#else
317272b676d7Smrg   somebase = pciReadWord(0x00001000, 0x74);
317372b676d7Smrg#endif
317472b676d7Smrg   somebase &= 0xffff;
317572b676d7Smrg
317672b676d7Smrg   if(somebase == 0) return;
317772b676d7Smrg
317872b676d7Smrg   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
317972b676d7Smrg
318072b676d7Smrg   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
318172b676d7Smrg      temp1 = 0x21;
318272b676d7Smrg      temp2 = 0x03;
318372b676d7Smrg      temp3 |= 0x08;
318472b676d7Smrg   } else {
318572b676d7Smrg      temp1 = 0x25;
318672b676d7Smrg      temp2 = 0x0b;
318772b676d7Smrg   }
318872b676d7Smrg
318972b676d7Smrg#ifdef SIS_LINUX_KERNEL
319072b676d7Smrg   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
319172b676d7Smrg   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
319272b676d7Smrg#else
319372b676d7Smrg   pciWriteByte(0x00000000, 0x7e, temp1);
319472b676d7Smrg   pciWriteByte(0x00000000, 0x8d, temp2);
319572b676d7Smrg#endif
319672b676d7Smrg
319772b676d7Smrg   SiS_SetRegByte((somebase + 0x85), temp3);
319872b676d7Smrg#endif
319972b676d7Smrg}
320072b676d7Smrg
320172b676d7Smrg/*********************************************/
320272b676d7Smrg/*      X.org/XFree86: SET SCREEN PITCH      */
320372b676d7Smrg/*********************************************/
320472b676d7Smrg
320572b676d7Smrg#ifdef SIS_XORG_XF86
320672b676d7Smrgstatic void
320772b676d7SmrgSiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
320872b676d7Smrg{
320972b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
321072b676d7Smrg   unsigned short HDisplay = pSiS->scrnPitch >> 3;
321172b676d7Smrg
321272b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
321372b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
321472b676d7Smrg}
321572b676d7Smrg
321672b676d7Smrgstatic void
321772b676d7SmrgSiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
321872b676d7Smrg{
321972b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
322072b676d7Smrg   unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
322172b676d7Smrg
322272b676d7Smrg    /* Unlock CRT2 */
322372b676d7Smrg   if(pSiS->VGAEngine == SIS_315_VGA)
322472b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
322572b676d7Smrg   else
322672b676d7Smrg      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
322772b676d7Smrg
322872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
322972b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
323072b676d7Smrg}
323172b676d7Smrg
323272b676d7Smrgstatic void
323372b676d7SmrgSiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
323472b676d7Smrg{
323572b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
323672b676d7Smrg   BOOLEAN isslavemode = FALSE;
323772b676d7Smrg
323872b676d7Smrg   if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
323972b676d7Smrg       ( ((pSiS->VGAEngine == SIS_300_VGA) &&
324072b676d7Smrg	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
324172b676d7Smrg	 ((pSiS->VGAEngine == SIS_315_VGA) &&
324272b676d7Smrg	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
324372b676d7Smrg      isslavemode = TRUE;
324472b676d7Smrg   }
324572b676d7Smrg
324672b676d7Smrg   /* We need to set pitch for CRT1 if bridge is in slave mode, too */
324772b676d7Smrg   if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) {
324872b676d7Smrg      SiS_SetPitchCRT1(SiS_Pr, pScrn);
324972b676d7Smrg   }
325072b676d7Smrg   /* We must not set the pitch for CRT2 if bridge is in slave mode */
325172b676d7Smrg   if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) {
325272b676d7Smrg      SiS_SetPitchCRT2(SiS_Pr, pScrn);
325372b676d7Smrg   }
325472b676d7Smrg}
325572b676d7Smrg#endif
325672b676d7Smrg
325772b676d7Smrg/*********************************************/
325872b676d7Smrg/*                 SiSSetMode()              */
325972b676d7Smrg/*********************************************/
326072b676d7Smrg
326172b676d7Smrg#ifdef SIS_XORG_XF86
326272b676d7Smrg/* We need pScrn for setting the pitch correctly */
326372b676d7SmrgBOOLEAN
326472b676d7SmrgSiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
326572b676d7Smrg#else
326672b676d7SmrgBOOLEAN
326772b676d7SmrgSiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
326872b676d7Smrg#endif
326972b676d7Smrg{
327072b676d7Smrg   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
327172b676d7Smrg   unsigned short RealModeNo, ModeIdIndex;
327272b676d7Smrg   unsigned char  backupreg = 0;
327372b676d7Smrg#ifdef SIS_LINUX_KERNEL
327472b676d7Smrg   unsigned short KeepLockReg;
327572b676d7Smrg
327672b676d7Smrg   SiS_Pr->UseCustomMode = FALSE;
327772b676d7Smrg   SiS_Pr->CRT1UsesCustomMode = FALSE;
327872b676d7Smrg#endif
327972b676d7Smrg
328072b676d7Smrg   SiS_Pr->SiS_flag_clearbuffer = 0;
328172b676d7Smrg
328272b676d7Smrg   if(SiS_Pr->UseCustomMode) {
328372b676d7Smrg      ModeNo = 0xfe;
328472b676d7Smrg   } else {
328572b676d7Smrg#ifdef SIS_LINUX_KERNEL
328672b676d7Smrg      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
328772b676d7Smrg#endif
328872b676d7Smrg      ModeNo &= 0x7f;
328972b676d7Smrg   }
329072b676d7Smrg
329172b676d7Smrg   /* Don't use FSTN mode for CRT1 */
329272b676d7Smrg   RealModeNo = ModeNo;
329372b676d7Smrg   if(ModeNo == 0x5b) ModeNo = 0x56;
329472b676d7Smrg
329572b676d7Smrg   SiSInitPtr(SiS_Pr);
329672b676d7Smrg   SiSRegInit(SiS_Pr, BaseAddr);
329772b676d7Smrg   SiS_GetSysFlags(SiS_Pr);
329872b676d7Smrg
329972b676d7Smrg   SiS_Pr->SiS_VGAINFO = 0x11;
330072b676d7Smrg#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
330172b676d7Smrg   if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
330272b676d7Smrg#endif
330372b676d7Smrg
330472b676d7Smrg#ifdef SIS_LINUX_KERNEL
330572b676d7Smrg   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
330672b676d7Smrg#endif
330772b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
330872b676d7Smrg
330972b676d7Smrg   SiSInitPCIetc(SiS_Pr);
331072b676d7Smrg   SiSSetLVDSetc(SiS_Pr);
331172b676d7Smrg   SiSDetermineROMUsage(SiS_Pr);
331272b676d7Smrg
331372b676d7Smrg   SiS_UnLockCRT2(SiS_Pr);
331472b676d7Smrg
331572b676d7Smrg   if(!SiS_Pr->UseCustomMode) {
331672b676d7Smrg      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
331772b676d7Smrg   } else {
331872b676d7Smrg      ModeIdIndex = 0;
331972b676d7Smrg   }
332072b676d7Smrg
332172b676d7Smrg   SiS_GetVBType(SiS_Pr);
332272b676d7Smrg
332372b676d7Smrg   /* Init/restore some VB registers */
332472b676d7Smrg   SiS_InitVB(SiS_Pr);
332572b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
332672b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
332772b676d7Smrg         SiS_ResetVB(SiS_Pr);
332872b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
332972b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
333072b676d7Smrg         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
333172b676d7Smrg      } else {
333272b676d7Smrg         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
333372b676d7Smrg      }
333472b676d7Smrg   }
333572b676d7Smrg
333672b676d7Smrg   /* Get VB information (connectors, connected devices) */
333772b676d7Smrg   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
333872b676d7Smrg   SiS_SetYPbPr(SiS_Pr);
333972b676d7Smrg   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
334072b676d7Smrg   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
334172b676d7Smrg   SiS_SetLowModeTest(SiS_Pr, ModeNo);
334272b676d7Smrg
334372b676d7Smrg#ifdef SIS_LINUX_KERNEL
334472b676d7Smrg   /* Check memory size (kernel framebuffer driver only) */
334572b676d7Smrg   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
334672b676d7Smrg      return FALSE;
334772b676d7Smrg   }
334872b676d7Smrg#endif
334972b676d7Smrg
335072b676d7Smrg   SiS_OpenCRTC(SiS_Pr);
335172b676d7Smrg
335272b676d7Smrg   if(SiS_Pr->UseCustomMode) {
335372b676d7Smrg      SiS_Pr->CRT1UsesCustomMode = TRUE;
335472b676d7Smrg      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
335572b676d7Smrg      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
335672b676d7Smrg   } else {
335772b676d7Smrg      SiS_Pr->CRT1UsesCustomMode = FALSE;
335872b676d7Smrg   }
335972b676d7Smrg
336072b676d7Smrg   /* Set mode on CRT1 */
336172b676d7Smrg   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
336272b676d7Smrg       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
336372b676d7Smrg      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
336472b676d7Smrg   }
336572b676d7Smrg
336672b676d7Smrg   /* Set mode on CRT2 */
336772b676d7Smrg   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
336872b676d7Smrg      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
336972b676d7Smrg	  (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
337072b676d7Smrg	  (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
337172b676d7Smrg	  (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
337272b676d7Smrg	 SiS_SetCRT2Group(SiS_Pr, RealModeNo);
337372b676d7Smrg      }
337472b676d7Smrg   }
337572b676d7Smrg
337672b676d7Smrg   SiS_HandleCRT1(SiS_Pr);
337772b676d7Smrg
337872b676d7Smrg   SiS_StrangeStuff(SiS_Pr);
337972b676d7Smrg
338072b676d7Smrg   SiS_DisplayOn(SiS_Pr);
338172b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
338272b676d7Smrg
338372b676d7Smrg#ifdef SIS315H
338472b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
338572b676d7Smrg      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
338672b676d7Smrg	 if(!(SiS_IsDualEdge(SiS_Pr))) {
338772b676d7Smrg	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
338872b676d7Smrg	 }
338972b676d7Smrg      }
339072b676d7Smrg   }
339172b676d7Smrg#endif
339272b676d7Smrg
339372b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
339472b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
339572b676d7Smrg#ifdef SIS315H
339672b676d7Smrg	 if(!SiS_Pr->SiS_ROMNew) {
339772b676d7Smrg	    if(SiS_IsVAMode(SiS_Pr)) {
339872b676d7Smrg	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
339972b676d7Smrg	    } else {
340072b676d7Smrg	       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
340172b676d7Smrg	    }
340272b676d7Smrg	 }
340372b676d7Smrg
340472b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
340572b676d7Smrg
340672b676d7Smrg	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
340772b676d7Smrg	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {
340872b676d7Smrg	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
340972b676d7Smrg	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
341072b676d7Smrg	    }
341172b676d7Smrg	 }
341272b676d7Smrg
341372b676d7Smrg	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
341472b676d7Smrg	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
341572b676d7Smrg	 }
341672b676d7Smrg#endif
341772b676d7Smrg      } else if((SiS_Pr->ChipType == SIS_630) ||
341872b676d7Smrg	        (SiS_Pr->ChipType == SIS_730)) {
341972b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
342072b676d7Smrg      }
342172b676d7Smrg   }
342272b676d7Smrg
342372b676d7Smrg#ifdef SIS_XORG_XF86
342472b676d7Smrg   if(pScrn) {
342572b676d7Smrg      /* SetPitch: Adapt to virtual size & position */
342672b676d7Smrg      if((ModeNo > 0x13) && (dosetpitch)) {
342772b676d7Smrg	 SiS_SetPitch(SiS_Pr, pScrn);
342872b676d7Smrg      }
342972b676d7Smrg
343072b676d7Smrg      /* Backup/Set ModeNo in BIOS scratch area */
343172b676d7Smrg      SiS_GetSetModeID(pScrn, ModeNo);
343272b676d7Smrg   }
343372b676d7Smrg#endif
343472b676d7Smrg
343572b676d7Smrg   SiS_CloseCRTC(SiS_Pr);
343672b676d7Smrg
343772b676d7Smrg   SiS_Handle760(SiS_Pr);
343872b676d7Smrg
343972b676d7Smrg#ifdef SIS_LINUX_KERNEL
344072b676d7Smrg   /* We never lock registers in XF86 */
344172b676d7Smrg   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
344272b676d7Smrg#endif
344372b676d7Smrg
344472b676d7Smrg   return TRUE;
344572b676d7Smrg}
344672b676d7Smrg
344772b676d7Smrg/*********************************************/
344872b676d7Smrg/*       X.org/XFree86: SiSBIOSSetMode()     */
344972b676d7Smrg/*           for non-Dual-Head mode          */
345072b676d7Smrg/*********************************************/
345172b676d7Smrg
345272b676d7Smrg#ifdef SIS_XORG_XF86
345372b676d7SmrgBOOLEAN
345472b676d7SmrgSiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
345572b676d7Smrg               DisplayModePtr mode, BOOLEAN IsCustom)
345672b676d7Smrg{
345772b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
345872b676d7Smrg   unsigned short ModeNo = 0;
345972b676d7Smrg
346072b676d7Smrg   SiS_Pr->UseCustomMode = FALSE;
346172b676d7Smrg
346272b676d7Smrg   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
346372b676d7Smrg
346472b676d7Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
346572b676d7Smrg		SiS_Pr->CHDisplay,
346672b676d7Smrg		(mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
346772b676d7Smrg		   (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
346872b676d7Smrg		      SiS_Pr->CVDisplay)));
346972b676d7Smrg
347072b676d7Smrg   } else {
347172b676d7Smrg
347272b676d7Smrg      /* Don't need vbflags here; checks done earlier */
347372b676d7Smrg      ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
347472b676d7Smrg      if(!ModeNo) return FALSE;
347572b676d7Smrg
347672b676d7Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
347772b676d7Smrg
347872b676d7Smrg   }
347972b676d7Smrg
348072b676d7Smrg   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
348172b676d7Smrg}
348272b676d7Smrg
348372b676d7Smrg/*********************************************/
348472b676d7Smrg/*    X.org/XFree86: SiSBIOSSetModeCRT2()    */
348572b676d7Smrg/*           for Dual-Head modes             */
348672b676d7Smrg/*********************************************/
348772b676d7Smrg
348872b676d7SmrgBOOLEAN
348972b676d7SmrgSiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
349072b676d7Smrg               DisplayModePtr mode, BOOLEAN IsCustom)
349172b676d7Smrg{
349272b676d7Smrg   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
349372b676d7Smrg   SISPtr  pSiS = SISPTR(pScrn);
349472b676d7Smrg#ifdef SISDUALHEAD
349572b676d7Smrg   SISEntPtr pSiSEnt = pSiS->entityPrivate;
349672b676d7Smrg#endif
349772b676d7Smrg   unsigned short ModeIdIndex;
349872b676d7Smrg   unsigned short ModeNo = 0;
349972b676d7Smrg   unsigned char  backupreg = 0;
350072b676d7Smrg
350172b676d7Smrg   SiS_Pr->UseCustomMode = FALSE;
350272b676d7Smrg
350372b676d7Smrg   /* Remember: Custom modes for CRT2 are ONLY supported
350472b676d7Smrg    *     -) on the 30x/B/C, and
350572b676d7Smrg    *     -) if CRT2 is LCD or VGA, or CRT1 is LCDA
350672b676d7Smrg    */
350772b676d7Smrg
350872b676d7Smrg   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
350972b676d7Smrg
351072b676d7Smrg	 ModeNo = 0xfe;
351172b676d7Smrg
351272b676d7Smrg   } else {
351372b676d7Smrg
351472b676d7Smrg	 ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
351572b676d7Smrg	 if(!ModeNo) return FALSE;
351672b676d7Smrg
351772b676d7Smrg   }
351872b676d7Smrg
351972b676d7Smrg   SiSRegInit(SiS_Pr, BaseAddr);
352072b676d7Smrg   SiSInitPtr(SiS_Pr);
352172b676d7Smrg   SiS_GetSysFlags(SiS_Pr);
352272b676d7Smrg#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
352372b676d7Smrg   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
352472b676d7Smrg#else
352572b676d7Smrg   SiS_Pr->SiS_VGAINFO = 0x11;
352672b676d7Smrg#endif
352772b676d7Smrg
352872b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
352972b676d7Smrg
353072b676d7Smrg   SiSInitPCIetc(SiS_Pr);
353172b676d7Smrg   SiSSetLVDSetc(SiS_Pr);
353272b676d7Smrg   SiSDetermineROMUsage(SiS_Pr);
353372b676d7Smrg
353472b676d7Smrg   /* Save mode info so we can set it from within SetMode for CRT1 */
353572b676d7Smrg#ifdef SISDUALHEAD
353672b676d7Smrg   if(pSiS->DualHeadMode) {
353772b676d7Smrg      pSiSEnt->CRT2ModeNo = ModeNo;
353872b676d7Smrg      pSiSEnt->CRT2DMode = mode;
353972b676d7Smrg      pSiSEnt->CRT2IsCustom = IsCustom;
354072b676d7Smrg      pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
354172b676d7Smrg      pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
354272b676d7Smrg      pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
354372b676d7Smrg      pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
354472b676d7Smrg#if 0
354572b676d7Smrg      /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
354672b676d7Smrg      if(pSiSEnt->CRT1ModeNo == -1) {
354772b676d7Smrg	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
354872b676d7Smrg		"Setting CRT2 mode delayed until after setting CRT1 mode\n");
354972b676d7Smrg	 return TRUE;
355072b676d7Smrg      }
355172b676d7Smrg#endif
355272b676d7Smrg      pSiSEnt->CRT2ModeSet = TRUE;
355372b676d7Smrg   }
355472b676d7Smrg#endif
355572b676d7Smrg
355672b676d7Smrg   if(SiS_Pr->UseCustomMode) {
355772b676d7Smrg
355872b676d7Smrg      unsigned short temptemp = SiS_Pr->CVDisplay;
355972b676d7Smrg
356072b676d7Smrg      if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
356172b676d7Smrg      else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
356272b676d7Smrg
356372b676d7Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
356472b676d7Smrg	  "Setting custom mode %dx%d on CRT2\n",
356572b676d7Smrg	  SiS_Pr->CHDisplay, temptemp);
356672b676d7Smrg
356772b676d7Smrg   } else {
356872b676d7Smrg
356972b676d7Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
357072b676d7Smrg	  "Setting standard mode 0x%x on CRT2\n", ModeNo);
357172b676d7Smrg
357272b676d7Smrg   }
357372b676d7Smrg
357472b676d7Smrg   SiS_UnLockCRT2(SiS_Pr);
357572b676d7Smrg
357672b676d7Smrg   if(!SiS_Pr->UseCustomMode) {
357772b676d7Smrg      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
357872b676d7Smrg   } else {
357972b676d7Smrg      ModeIdIndex = 0;
358072b676d7Smrg   }
358172b676d7Smrg
358272b676d7Smrg   SiS_GetVBType(SiS_Pr);
358372b676d7Smrg
358472b676d7Smrg   SiS_InitVB(SiS_Pr);
358572b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
358672b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
358772b676d7Smrg	 SiS_ResetVB(SiS_Pr);
358872b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
358972b676d7Smrg	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
359072b676d7Smrg	 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
359172b676d7Smrg      } else {
359272b676d7Smrg	 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
359372b676d7Smrg      }
359472b676d7Smrg   }
359572b676d7Smrg
359672b676d7Smrg   /* Get VB information (connectors, connected devices) */
359772b676d7Smrg   if(!SiS_Pr->UseCustomMode) {
359872b676d7Smrg      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
359972b676d7Smrg   } else {
360072b676d7Smrg      /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
360172b676d7Smrg      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
360272b676d7Smrg   }
360372b676d7Smrg   SiS_SetYPbPr(SiS_Pr);
360472b676d7Smrg   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
360572b676d7Smrg   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
360672b676d7Smrg   SiS_SetLowModeTest(SiS_Pr, ModeNo);
360772b676d7Smrg
360872b676d7Smrg   SiS_ResetSegmentRegisters(SiS_Pr);
360972b676d7Smrg
361072b676d7Smrg   /* Set mode on CRT2 */
361172b676d7Smrg   if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
361272b676d7Smrg       (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
361372b676d7Smrg       (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
361472b676d7Smrg       (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
361572b676d7Smrg      SiS_SetCRT2Group(SiS_Pr, ModeNo);
361672b676d7Smrg   }
361772b676d7Smrg
361872b676d7Smrg   SiS_StrangeStuff(SiS_Pr);
361972b676d7Smrg
362072b676d7Smrg   SiS_DisplayOn(SiS_Pr);
362172b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
362272b676d7Smrg
362372b676d7Smrg   if(SiS_Pr->ChipType >= SIS_315H) {
362472b676d7Smrg      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
362572b676d7Smrg	 if(!(SiS_IsDualEdge(SiS_Pr))) {
362672b676d7Smrg	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
362772b676d7Smrg	 }
362872b676d7Smrg      }
362972b676d7Smrg   }
363072b676d7Smrg
363172b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
363272b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
363372b676d7Smrg	 if(!SiS_Pr->SiS_ROMNew) {
363472b676d7Smrg	    if(SiS_IsVAMode(SiS_Pr)) {
363572b676d7Smrg	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
363672b676d7Smrg	    } else {
363772b676d7Smrg	       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
363872b676d7Smrg	    }
363972b676d7Smrg	 }
364072b676d7Smrg
364172b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
364272b676d7Smrg
364372b676d7Smrg	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
364472b676d7Smrg	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
364572b676d7Smrg	 }
364672b676d7Smrg      } else if((SiS_Pr->ChipType == SIS_630) ||
364772b676d7Smrg	        (SiS_Pr->ChipType == SIS_730)) {
364872b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
364972b676d7Smrg      }
365072b676d7Smrg   }
365172b676d7Smrg
365272b676d7Smrg   /* SetPitch: Adapt to virtual size & position */
365372b676d7Smrg   SiS_SetPitchCRT2(SiS_Pr, pScrn);
365472b676d7Smrg
365572b676d7Smrg   SiS_Handle760(SiS_Pr);
365672b676d7Smrg
365772b676d7Smrg   return TRUE;
365872b676d7Smrg}
365972b676d7Smrg
366072b676d7Smrg/*********************************************/
366172b676d7Smrg/*    X.org/XFree86: SiSBIOSSetModeCRT1()    */
366272b676d7Smrg/*           for Dual-Head modes             */
366372b676d7Smrg/*********************************************/
366472b676d7Smrg
366572b676d7SmrgBOOLEAN
366672b676d7SmrgSiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
366772b676d7Smrg                   DisplayModePtr mode, BOOLEAN IsCustom)
366872b676d7Smrg{
366972b676d7Smrg   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
367072b676d7Smrg   SISPtr  pSiS = SISPTR(pScrn);
367172b676d7Smrg   unsigned short ModeIdIndex, ModeNo = 0;
367272b676d7Smrg   unsigned char  backupreg = 0;
367372b676d7Smrg#ifdef SISDUALHEAD
367472b676d7Smrg   SISEntPtr pSiSEnt = pSiS->entityPrivate;
367572b676d7Smrg   unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
367672b676d7Smrg   BOOLEAN backupcustom;
367772b676d7Smrg#endif
367872b676d7Smrg
367972b676d7Smrg   SiS_Pr->UseCustomMode = FALSE;
368072b676d7Smrg
368172b676d7Smrg   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
368272b676d7Smrg
368372b676d7Smrg	 unsigned short temptemp = SiS_Pr->CVDisplay;
368472b676d7Smrg
368572b676d7Smrg	 if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
368672b676d7Smrg	 else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
368772b676d7Smrg
368872b676d7Smrg	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
368972b676d7Smrg	 	"Setting custom mode %dx%d on CRT1\n",
369072b676d7Smrg	 	SiS_Pr->CHDisplay, temptemp);
369172b676d7Smrg	 ModeNo = 0xfe;
369272b676d7Smrg
369372b676d7Smrg   } else {
369472b676d7Smrg
369572b676d7Smrg	 ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
369672b676d7Smrg	 if(!ModeNo) return FALSE;
369772b676d7Smrg
369872b676d7Smrg	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
369972b676d7Smrg	 	"Setting standard mode 0x%x on CRT1\n", ModeNo);
370072b676d7Smrg   }
370172b676d7Smrg
370272b676d7Smrg   SiSInitPtr(SiS_Pr);
370372b676d7Smrg   SiSRegInit(SiS_Pr, BaseAddr);
370472b676d7Smrg   SiS_GetSysFlags(SiS_Pr);
370572b676d7Smrg#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
370672b676d7Smrg   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
370772b676d7Smrg#else
370872b676d7Smrg   SiS_Pr->SiS_VGAINFO = 0x11;
370972b676d7Smrg#endif
371072b676d7Smrg
371172b676d7Smrg   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
371272b676d7Smrg
371372b676d7Smrg   SiSInitPCIetc(SiS_Pr);
371472b676d7Smrg   SiSSetLVDSetc(SiS_Pr);
371572b676d7Smrg   SiSDetermineROMUsage(SiS_Pr);
371672b676d7Smrg
371772b676d7Smrg   SiS_UnLockCRT2(SiS_Pr);
371872b676d7Smrg
371972b676d7Smrg   if(!SiS_Pr->UseCustomMode) {
372072b676d7Smrg      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
372172b676d7Smrg   } else {
372272b676d7Smrg      ModeIdIndex = 0;
372372b676d7Smrg   }
372472b676d7Smrg
372572b676d7Smrg   /* Determine VBType */
372672b676d7Smrg   SiS_GetVBType(SiS_Pr);
372772b676d7Smrg
372872b676d7Smrg   SiS_InitVB(SiS_Pr);
372972b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
373072b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
373172b676d7Smrg         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
373272b676d7Smrg      } else {
373372b676d7Smrg         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
373472b676d7Smrg      }
373572b676d7Smrg   }
373672b676d7Smrg
373772b676d7Smrg   /* Get VB information (connectors, connected devices) */
373872b676d7Smrg   /* (We don't care if the current mode is a CRT2 mode) */
373972b676d7Smrg   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
374072b676d7Smrg   SiS_SetYPbPr(SiS_Pr);
374172b676d7Smrg   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
374272b676d7Smrg   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
374372b676d7Smrg   SiS_SetLowModeTest(SiS_Pr, ModeNo);
374472b676d7Smrg
374572b676d7Smrg   SiS_OpenCRTC(SiS_Pr);
374672b676d7Smrg
374772b676d7Smrg   /* Set mode on CRT1 */
374872b676d7Smrg   SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
374972b676d7Smrg   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
375072b676d7Smrg      SiS_SetCRT2Group(SiS_Pr, ModeNo);
375172b676d7Smrg   }
375272b676d7Smrg
375372b676d7Smrg   /* SetPitch: Adapt to virtual size & position */
375472b676d7Smrg   SiS_SetPitchCRT1(SiS_Pr, pScrn);
375572b676d7Smrg
375672b676d7Smrg   SiS_HandleCRT1(SiS_Pr);
375772b676d7Smrg
375872b676d7Smrg   SiS_StrangeStuff(SiS_Pr);
375972b676d7Smrg
376072b676d7Smrg   SiS_CloseCRTC(SiS_Pr);
376172b676d7Smrg
376272b676d7Smrg#ifdef SISDUALHEAD
376372b676d7Smrg   if(pSiS->DualHeadMode) {
376472b676d7Smrg      pSiSEnt->CRT1ModeNo = ModeNo;
376572b676d7Smrg      pSiSEnt->CRT1DMode = mode;
376672b676d7Smrg   }
376772b676d7Smrg#endif
376872b676d7Smrg
376972b676d7Smrg   if(SiS_Pr->UseCustomMode) {
377072b676d7Smrg      SiS_Pr->CRT1UsesCustomMode = TRUE;
377172b676d7Smrg      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
377272b676d7Smrg      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
377372b676d7Smrg   } else {
377472b676d7Smrg      SiS_Pr->CRT1UsesCustomMode = FALSE;
377572b676d7Smrg   }
377672b676d7Smrg
377772b676d7Smrg   /* Reset CRT2 if changing mode on CRT1 */
377872b676d7Smrg#ifdef SISDUALHEAD
377972b676d7Smrg   if(pSiS->DualHeadMode) {
378072b676d7Smrg      if(pSiSEnt->CRT2ModeNo != -1) {
378172b676d7Smrg	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
378272b676d7Smrg				"(Re-)Setting mode for CRT2\n");
378372b676d7Smrg	 backupcustom = SiS_Pr->UseCustomMode;
378472b676d7Smrg	 backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
378572b676d7Smrg	 backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
378672b676d7Smrg	 backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
378772b676d7Smrg	 backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
378872b676d7Smrg	 if(SiS_Pr->SiS_VBType & VB_SISVB) {
378972b676d7Smrg	    /* Backup LUT-enable */
379072b676d7Smrg	    if(pSiSEnt->CRT2ModeSet) {
379172b676d7Smrg	       backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08;
379272b676d7Smrg	    }
379372b676d7Smrg	 }
379472b676d7Smrg	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
379572b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30);
379672b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31);
379772b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
379872b676d7Smrg	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
379972b676d7Smrg	 }
380072b676d7Smrg
380172b676d7Smrg	 SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
380272b676d7Smrg			    pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
380372b676d7Smrg
380472b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
380572b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
380672b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
380772b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
380872b676d7Smrg	 if(SiS_Pr->SiS_VBType & VB_SISVB) {
380972b676d7Smrg	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d);
381072b676d7Smrg	 }
381172b676d7Smrg	 SiS_Pr->UseCustomMode = backupcustom;
381272b676d7Smrg      }
381372b676d7Smrg   }
381472b676d7Smrg#endif
381572b676d7Smrg
381672b676d7Smrg   /* Warning: From here, the custom mode entries in SiS_Pr are
381772b676d7Smrg    * possibly overwritten
381872b676d7Smrg    */
381972b676d7Smrg
382072b676d7Smrg   SiS_DisplayOn(SiS_Pr);
382172b676d7Smrg   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
382272b676d7Smrg
382372b676d7Smrg   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
382472b676d7Smrg      if(SiS_Pr->ChipType >= SIS_315H) {
382572b676d7Smrg	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
382672b676d7Smrg      } else if((SiS_Pr->ChipType == SIS_630) ||
382772b676d7Smrg                (SiS_Pr->ChipType == SIS_730)) {
382872b676d7Smrg         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
382972b676d7Smrg      }
383072b676d7Smrg   }
383172b676d7Smrg
383272b676d7Smrg   SiS_Handle760(SiS_Pr);
383372b676d7Smrg
383472b676d7Smrg   /* Backup/Set ModeNo in BIOS scratch area */
383572b676d7Smrg   SiS_GetSetModeID(pScrn,ModeNo);
383672b676d7Smrg
383772b676d7Smrg   return TRUE;
383872b676d7Smrg}
383972b676d7Smrg#endif /* Linux_XF86 */
384072b676d7Smrg
384172b676d7Smrg#ifndef GETBITSTR
384272b676d7Smrg#define BITMASK(h,l)    	(((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
384372b676d7Smrg#define GENMASK(mask)   	BITMASK(1?mask,0?mask)
384472b676d7Smrg#define GETBITS(var,mask)   	(((var) & GENMASK(mask)) >> (0?mask))
384572b676d7Smrg#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
384672b676d7Smrg#endif
384772b676d7Smrg
384872b676d7Smrgvoid
384972b676d7SmrgSiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
385072b676d7Smrg{
385172b676d7Smrg   int x = 1; /* Fix sync */
385272b676d7Smrg
385372b676d7Smrg   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
385472b676d7Smrg   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
385572b676d7Smrg   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
385672b676d7Smrg   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
385772b676d7Smrg   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
385872b676d7Smrg   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
385972b676d7Smrg			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
386072b676d7Smrg
386172b676d7Smrg   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;			/* CR6 */
386272b676d7Smrg   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)		/* CR7 */
386372b676d7Smrg			  | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
386472b676d7Smrg			  | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
386572b676d7Smrg			  | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
386672b676d7Smrg			  | 0x10
386772b676d7Smrg			  | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
386872b676d7Smrg			  | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
386972b676d7Smrg			  | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
387072b676d7Smrg
387172b676d7Smrg   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
387272b676d7Smrg
387372b676d7Smrg   if(depth != 8) {
387472b676d7Smrg      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
387572b676d7Smrg      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
387672b676d7Smrg   }
387772b676d7Smrg
387872b676d7Smrg   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;			/* CR10 */
387972b676d7Smrg   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;		/* CR11 */
388072b676d7Smrg   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
388172b676d7Smrg   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
388272b676d7Smrg   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
388372b676d7Smrg
388472b676d7Smrg   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
388572b676d7Smrg			GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
388672b676d7Smrg			GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
388772b676d7Smrg			GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
388872b676d7Smrg			GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
388972b676d7Smrg			GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
389072b676d7Smrg			GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
389172b676d7Smrg
389272b676d7Smrg   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
389372b676d7Smrg			GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
389472b676d7Smrg			GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
389572b676d7Smrg			GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
389672b676d7Smrg			GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
389772b676d7Smrg
389872b676d7Smrg
389972b676d7Smrg   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
390072b676d7Smrg			GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
390172b676d7Smrg			GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
390272b676d7Smrg}
390372b676d7Smrg
390472b676d7Smrgvoid
390572b676d7SmrgSiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
390672b676d7Smrg		unsigned short ModeIdIndex)
390772b676d7Smrg{
390872b676d7Smrg   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
390972b676d7Smrg   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
391072b676d7Smrg   int i, j;
391172b676d7Smrg
391272b676d7Smrg   /* 1:1 data: use data set by setcrt1crtc() */
391372b676d7Smrg   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
391472b676d7Smrg
391572b676d7Smrg   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
391672b676d7Smrg
391772b676d7Smrg   if(modeflag & HalfDCLK) VGAHDE >>= 1;
391872b676d7Smrg
391972b676d7Smrg   SiS_Pr->CHDisplay = VGAHDE;
392072b676d7Smrg   SiS_Pr->CHBlankStart = VGAHDE;
392172b676d7Smrg
392272b676d7Smrg   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
392372b676d7Smrg   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
392472b676d7Smrg
392572b676d7Smrg   if(SiS_Pr->ChipType < SIS_315H) {
392672b676d7Smrg#ifdef SIS300
392772b676d7Smrg      tempbx = SiS_Pr->SiS_VGAHT;
392872b676d7Smrg      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
392972b676d7Smrg         tempbx = SiS_Pr->PanelHT;
393072b676d7Smrg      }
393172b676d7Smrg      if(modeflag & HalfDCLK) tempbx >>= 1;
393272b676d7Smrg      remaining = tempbx % 8;
393372b676d7Smrg#endif
393472b676d7Smrg   } else {
393572b676d7Smrg#ifdef SIS315H
393672b676d7Smrg      /* OK for LCDA, LVDS */
393772b676d7Smrg      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
393872b676d7Smrg      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
393972b676d7Smrg      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
394072b676d7Smrg         tempax = SiS_Pr->PanelXRes;
394172b676d7Smrg      }
394272b676d7Smrg      tempbx += tempax;
394372b676d7Smrg      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
394472b676d7Smrg#endif
394572b676d7Smrg   }
394672b676d7Smrg   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
394772b676d7Smrg
394872b676d7Smrg   if(SiS_Pr->ChipType < SIS_315H) {
394972b676d7Smrg#ifdef SIS300
395072b676d7Smrg      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
395172b676d7Smrg	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
395272b676d7Smrg	 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
395372b676d7Smrg	 if(modeflag & HalfDCLK) {
395472b676d7Smrg	    SiS_Pr->CHSyncStart >>= 1;
395572b676d7Smrg	    SiS_Pr->CHSyncEnd >>= 1;
395672b676d7Smrg	 }
395772b676d7Smrg      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
395872b676d7Smrg	 tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
395972b676d7Smrg	 tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
396072b676d7Smrg	 if(modeflag & HalfDCLK) {
396172b676d7Smrg	    tempax >>= 1;
396272b676d7Smrg	    tempbx >>= 1;
396372b676d7Smrg	 }
396472b676d7Smrg	 SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
396572b676d7Smrg	 tempax = SiS_Pr->PanelHRE + 7;
396672b676d7Smrg	 if(modeflag & HalfDCLK) tempax >>= 1;
396772b676d7Smrg	 SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
396872b676d7Smrg      } else {
396972b676d7Smrg	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
397072b676d7Smrg	 if(modeflag & HalfDCLK) {
397172b676d7Smrg	    SiS_Pr->CHSyncStart >>= 1;
397272b676d7Smrg	    tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
397372b676d7Smrg	    SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
397472b676d7Smrg	 } else {
397572b676d7Smrg	    SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
397672b676d7Smrg	    SiS_Pr->CHSyncStart += 8;
397772b676d7Smrg	 }
397872b676d7Smrg      }
397972b676d7Smrg#endif
398072b676d7Smrg   } else {
398172b676d7Smrg#ifdef SIS315H
398272b676d7Smrg      tempax = VGAHDE;
398372b676d7Smrg      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
398472b676d7Smrg	 tempbx = SiS_Pr->PanelXRes;
398572b676d7Smrg	 if(modeflag & HalfDCLK) tempbx >>= 1;
398672b676d7Smrg	 tempax += ((tempbx - tempax) >> 1);
398772b676d7Smrg      }
398872b676d7Smrg      tempax += SiS_Pr->PanelHRS;
398972b676d7Smrg      SiS_Pr->CHSyncStart = tempax;
399072b676d7Smrg      tempax += SiS_Pr->PanelHRE;
399172b676d7Smrg      SiS_Pr->CHSyncEnd = tempax;
399272b676d7Smrg#endif
399372b676d7Smrg   }
399472b676d7Smrg
399572b676d7Smrg   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
399672b676d7Smrg   tempax = SiS_Pr->SiS_VGAVDE;
399772b676d7Smrg   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
399872b676d7Smrg      tempax = SiS_Pr->PanelYRes;
399972b676d7Smrg   } else if(SiS_Pr->ChipType < SIS_315H) {
400072b676d7Smrg#ifdef SIS300
400172b676d7Smrg      /* Stupid hack for 640x400/320x200 */
400272b676d7Smrg      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
400372b676d7Smrg	 if((tempax + tempbx) == 438) tempbx += 16;
400472b676d7Smrg      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
400572b676d7Smrg		(SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
400672b676d7Smrg	 tempax = 0;
400772b676d7Smrg	 tempbx = SiS_Pr->SiS_VGAVT;
400872b676d7Smrg      }
400972b676d7Smrg#endif
401072b676d7Smrg   }
401172b676d7Smrg   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
401272b676d7Smrg
401372b676d7Smrg   tempax = SiS_Pr->SiS_VGAVDE;
401472b676d7Smrg   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
401572b676d7Smrg      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
401672b676d7Smrg   }
401772b676d7Smrg   tempax += SiS_Pr->PanelVRS;
401872b676d7Smrg   SiS_Pr->CVSyncStart = tempax;
401972b676d7Smrg   tempax += SiS_Pr->PanelVRE;
402072b676d7Smrg   SiS_Pr->CVSyncEnd = tempax;
402172b676d7Smrg   if(SiS_Pr->ChipType < SIS_315H) {
402272b676d7Smrg      SiS_Pr->CVSyncStart--;
402372b676d7Smrg      SiS_Pr->CVSyncEnd--;
402472b676d7Smrg   }
402572b676d7Smrg
402672b676d7Smrg   SiS_CalcCRRegisters(SiS_Pr, 8);
402772b676d7Smrg   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
402872b676d7Smrg   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
402972b676d7Smrg   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
403072b676d7Smrg
403172b676d7Smrg   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
403272b676d7Smrg
403372b676d7Smrg   for(i = 0, j = 0; i <= 7; i++, j++) {
403472b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
403572b676d7Smrg   }
403672b676d7Smrg   for(j = 0x10; i <= 10; i++, j++) {
403772b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
403872b676d7Smrg   }
403972b676d7Smrg   for(j = 0x15; i <= 12; i++, j++) {
404072b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
404172b676d7Smrg   }
404272b676d7Smrg   for(j = 0x0A; i <= 15; i++, j++) {
404372b676d7Smrg      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
404472b676d7Smrg   }
404572b676d7Smrg
404672b676d7Smrg   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
404772b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
404872b676d7Smrg
404972b676d7Smrg   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
405072b676d7Smrg   if(modeflag & DoubleScanMode) tempax |= 0x80;
405172b676d7Smrg   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
405272b676d7Smrg
405372b676d7Smrg#ifdef SIS_XORG_XF86
405472b676d7Smrg#ifdef TWDEBUG
405572b676d7Smrg   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
405672b676d7Smrg	SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
405772b676d7Smrg	SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
405872b676d7Smrg	SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
405972b676d7Smrg   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
406072b676d7Smrg	SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
406172b676d7Smrg	SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
406272b676d7Smrg	SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
406372b676d7Smrg	SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
406472b676d7Smrg   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
406572b676d7Smrg	SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
406672b676d7Smrg	SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
406772b676d7Smrg	SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
406872b676d7Smrg	SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
406972b676d7Smrg   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
407072b676d7Smrg#endif
407172b676d7Smrg#endif
407272b676d7Smrg}
407372b676d7Smrg
407472b676d7Smrgvoid
407572b676d7SmrgSiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
407672b676d7Smrg			int xres, int yres,
407772b676d7Smrg#ifdef SIS_XORG_XF86
407872b676d7Smrg			DisplayModePtr current
407972b676d7Smrg#endif
408072b676d7Smrg#ifdef SIS_LINUX_KERNEL
408172b676d7Smrg			struct fb_var_screeninfo *var, BOOLEAN writeres
408272b676d7Smrg#endif
408372b676d7Smrg)
408472b676d7Smrg{
408572b676d7Smrg   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
408672b676d7Smrg   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
408772b676d7Smrg   unsigned char  sr_data, cr_data, cr_data2;
408872b676d7Smrg   int            A, B, C, D, E, F, temp;
408972b676d7Smrg
409072b676d7Smrg   sr_data = crdata[14];
409172b676d7Smrg
409272b676d7Smrg   /* Horizontal total */
409372b676d7Smrg   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
409472b676d7Smrg   A = HT + 5;
409572b676d7Smrg
409672b676d7Smrg   /* Horizontal display enable end */
409772b676d7Smrg   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
409872b676d7Smrg   E = HDE + 1;
409972b676d7Smrg
410072b676d7Smrg   /* Horizontal retrace (=sync) start */
410172b676d7Smrg   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
410272b676d7Smrg   F = HRS - E - 3;
410372b676d7Smrg
410472b676d7Smrg   /* Horizontal blank start */
410572b676d7Smrg   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
410672b676d7Smrg
410772b676d7Smrg   sr_data = crdata[15];
410872b676d7Smrg   cr_data = crdata[5];
410972b676d7Smrg
411072b676d7Smrg   /* Horizontal blank end */
411172b676d7Smrg   HBE = (crdata[3] & 0x1f) |
411272b676d7Smrg         ((unsigned short)(cr_data & 0x80) >> 2) |
411372b676d7Smrg         ((unsigned short)(sr_data & 0x03) << 6);
411472b676d7Smrg
411572b676d7Smrg   /* Horizontal retrace (=sync) end */
411672b676d7Smrg   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
411772b676d7Smrg
411872b676d7Smrg   temp = HBE - ((E - 1) & 255);
411972b676d7Smrg   B = (temp > 0) ? temp : (temp + 256);
412072b676d7Smrg
412172b676d7Smrg   temp = HRE - ((E + F + 3) & 63);
412272b676d7Smrg   C = (temp > 0) ? temp : (temp + 64);
412372b676d7Smrg
412472b676d7Smrg   D = B - F - C;
412572b676d7Smrg
412672b676d7Smrg#ifdef SIS_XORG_XF86
412772b676d7Smrg   current->HDisplay   = (E * 8);
412872b676d7Smrg   current->HSyncStart = (E * 8) + (F * 8);
412972b676d7Smrg   current->HSyncEnd   = (E * 8) + (F * 8) + (C * 8);
413072b676d7Smrg   current->HTotal     = (E * 8) + (F * 8) + (C * 8) + (D * 8);
413172b676d7Smrg#ifdef TWDEBUG
413272b676d7Smrg   xf86DrvMsg(0, X_INFO,
413372b676d7Smrg		"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",
413472b676d7Smrg		A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
413572b676d7Smrg#else
413672b676d7Smrg   (void)VBS;  (void)HBS;  (void)A;
413772b676d7Smrg#endif
413872b676d7Smrg#endif
413972b676d7Smrg#ifdef SIS_LINUX_KERNEL
414072b676d7Smrg   if(writeres) var->xres = xres = E * 8;
414172b676d7Smrg   var->left_margin = D * 8;
414272b676d7Smrg   var->right_margin = F * 8;
414372b676d7Smrg   var->hsync_len = C * 8;
414472b676d7Smrg#endif
414572b676d7Smrg
414672b676d7Smrg   /* Vertical */
414772b676d7Smrg   sr_data = crdata[13];
414872b676d7Smrg   cr_data = crdata[7];
414972b676d7Smrg
415072b676d7Smrg   /* Vertical total */
415172b676d7Smrg   VT  = crdata[6] |
415272b676d7Smrg	 ((unsigned short)(cr_data & 0x01) << 8) |
415372b676d7Smrg	 ((unsigned short)(cr_data & 0x20) << 4) |
415472b676d7Smrg	 ((unsigned short)(sr_data & 0x01) << 10);
415572b676d7Smrg   A = VT + 2;
415672b676d7Smrg
415772b676d7Smrg   /* Vertical display enable end */
415872b676d7Smrg   VDE = crdata[10] |
415972b676d7Smrg	 ((unsigned short)(cr_data & 0x02) << 7) |
416072b676d7Smrg	 ((unsigned short)(cr_data & 0x40) << 3) |
416172b676d7Smrg	 ((unsigned short)(sr_data & 0x02) << 9);
416272b676d7Smrg   E = VDE + 1;
416372b676d7Smrg
416472b676d7Smrg   /* Vertical retrace (=sync) start */
416572b676d7Smrg   VRS = crdata[8] |
416672b676d7Smrg	 ((unsigned short)(cr_data & 0x04) << 6) |
416772b676d7Smrg	 ((unsigned short)(cr_data & 0x80) << 2) |
416872b676d7Smrg	 ((unsigned short)(sr_data & 0x08) << 7);
416972b676d7Smrg   F = VRS + 1 - E;
417072b676d7Smrg
417172b676d7Smrg   cr_data2 = (crdata[16] & 0x01) << 5;
417272b676d7Smrg
417372b676d7Smrg   /* Vertical blank start */
417472b676d7Smrg   VBS = crdata[11] |
417572b676d7Smrg	 ((unsigned short)(cr_data  & 0x08) << 5) |
417672b676d7Smrg	 ((unsigned short)(cr_data2 & 0x20) << 4) |
417772b676d7Smrg	 ((unsigned short)(sr_data  & 0x04) << 8);
417872b676d7Smrg
417972b676d7Smrg   /* Vertical blank end */
418072b676d7Smrg   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
418172b676d7Smrg   temp = VBE - ((E - 1) & 511);
418272b676d7Smrg   B = (temp > 0) ? temp : (temp + 512);
418372b676d7Smrg
418472b676d7Smrg   /* Vertical retrace (=sync) end */
418572b676d7Smrg   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
418672b676d7Smrg   temp = VRE - ((E + F - 1) & 31);
418772b676d7Smrg   C = (temp > 0) ? temp : (temp + 32);
418872b676d7Smrg
418972b676d7Smrg   D = B - F - C;
419072b676d7Smrg
419172b676d7Smrg#ifdef SIS_XORG_XF86
419272b676d7Smrg   current->VDisplay   = VDE + 1;
419372b676d7Smrg   current->VSyncStart = VRS + 1;
419472b676d7Smrg   current->VSyncEnd   = ((VRS & ~0x1f) | VRE) + 1;
419572b676d7Smrg   if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
419672b676d7Smrg   current->VTotal     = E + D + C + F;
419772b676d7Smrg#if 0
419872b676d7Smrg   current->VDisplay   = E;
419972b676d7Smrg   current->VSyncStart = E + D;
420072b676d7Smrg   current->VSyncEnd   = E + D + C;
420172b676d7Smrg   current->VTotal     = E + D + C + F;
420272b676d7Smrg#endif
420372b676d7Smrg#ifdef TWDEBUG
420472b676d7Smrg   xf86DrvMsg(0, X_INFO,
420572b676d7Smrg	"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",
420672b676d7Smrg	A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
420772b676d7Smrg#endif
420872b676d7Smrg#endif
420972b676d7Smrg#ifdef SIS_LINUX_KERNEL
421072b676d7Smrg   if(writeres) var->yres = yres = E;
421172b676d7Smrg   var->upper_margin = D;
421272b676d7Smrg   var->lower_margin = F;
421372b676d7Smrg   var->vsync_len = C;
421472b676d7Smrg#endif
421572b676d7Smrg
421672b676d7Smrg   if((xres == 320) && ((yres == 200) || (yres == 240))) {
421772b676d7Smrg	/* Terrible hack, but correct CRTC data for
421872b676d7Smrg	 * these modes only produces a black screen...
421972b676d7Smrg	 * (HRE is 0, leading into a too large C and
422072b676d7Smrg	 * a negative D. The CRT controller does not
422172b676d7Smrg	 * seem to like correcting HRE to 50)
422272b676d7Smrg	 */
422372b676d7Smrg#ifdef SIS_XORG_XF86
422472b676d7Smrg      current->HDisplay   = 320;
422572b676d7Smrg      current->HSyncStart = 328;
422672b676d7Smrg      current->HSyncEnd   = 376;
422772b676d7Smrg      current->HTotal     = 400;
422872b676d7Smrg#endif
422972b676d7Smrg#ifdef SIS_LINUX_KERNEL
423072b676d7Smrg      var->left_margin = (400 - 376);
423172b676d7Smrg      var->right_margin = (328 - 320);
423272b676d7Smrg      var->hsync_len = (376 - 328);
423372b676d7Smrg#endif
423472b676d7Smrg
423572b676d7Smrg   }
423672b676d7Smrg
423772b676d7Smrg}
423872b676d7Smrg
423972b676d7Smrg
424072b676d7Smrg
424172b676d7Smrg
4242