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