Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  init.c   Sprache: C

 
/* $XFree86$ */
/* $XdotOrg$ */
/*
 * Mode initializing code (CRT1 section) for
 * for SiS 300/305/540/630/730,
 *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
 *     XGI Volari V3XT/V5/V8, Z7
 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
 *
 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
 *
 * If distributed as part of the Linux kernel, the following license terms
 * apply:
 *
 * * This program is free software; you can redistribute it and/or modify
 * * it under the terms of the GNU General Public License as published by
 * * the Free Software Foundation; either version 2 of the named License,
 * * or any later version.
 * *
 * * This program is distributed in the hope that it will be useful,
 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * * GNU General Public License for more details.
 * *
 * * You should have received a copy of the GNU General Public License
 * * along with this program; if not, write to the Free Software
 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
 *
 * Otherwise, the following license terms apply:
 *
 * * Redistribution and use in source and binary forms, with or without
 * * modification, are permitted provided that the following conditions
 * * are met:
 * * 1) Redistributions of source code must retain the above copyright
 * *    notice, this list of conditions and the following disclaimer.
 * * 2) Redistributions in binary form must reproduce the above copyright
 * *    notice, this list of conditions and the following disclaimer in the
 * *    documentation and/or other materials provided with the distribution.
 * * 3) The name of the author may not be used to endorse or promote products
 * *    derived from this software without specific prior written permission.
 * *
 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Author:  Thomas Winischhofer <thomas@winischhofer.net>
 *
 * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
 * Used by permission.
 */


#include "init.h"

#ifdef CONFIG_FB_SIS_300
#include "300vtbl.h"
#endif

#ifdef CONFIG_FB_SIS_315
#include "310vtbl.h"
#endif

#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,SiSSetMode)
#endif

/*********************************************/
/*         POINTER INITIALIZATION            */
/*********************************************/

#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
static void
InitCommonPointer(struct SiS_Private *SiS_Pr)
{
   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
   SiS_Pr->SiS_StandTable    = SiS_StandTable;

   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;

   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
#if 0
   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
#endif

   SiS_Pr->SiS_StPALData   = SiS_StPALData;
   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
   SiS_Pr->SiS_St525pData  = SiS_St525pData;
   SiS_Pr->SiS_St750pData  = SiS_St750pData;
   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;

   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;

   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;

   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;

   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
#if 0
   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
#endif

   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;

   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
}
#endif

#ifdef CONFIG_FB_SIS_300
static void
InitTo300Pointer(struct SiS_Private *SiS_Pr)
{
   InitCommonPointer(SiS_Pr);

   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
   if(SiS_Pr->ChipType == SIS_300) {
      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
   } else {
      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
   }
   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;

   SiS_Pr->SiS_SR15  = SiS300_SR15;

   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;

   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;

   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;

   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;

   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;

   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;

   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;
   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */
   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
}
#endif

#ifdef CONFIG_FB_SIS_315
static void
InitTo310Pointer(struct SiS_Private *SiS_Pr)
{
   InitCommonPointer(SiS_Pr);

   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
   if(SiS_Pr->ChipType >= SIS_340) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
   } else if(SiS_Pr->ChipType >= SIS_761) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
   } else if(SiS_Pr->ChipType >= SIS_760) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
   } else if(SiS_Pr->ChipType >= SIS_661) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
   } else if(SiS_Pr->ChipType == SIS_330) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
   } else if(SiS_Pr->ChipType > SIS_315PRO) {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
   } else {
      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
   }
   if(SiS_Pr->ChipType >= SIS_340) {
      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
   } else {
      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
   }
   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;

   SiS_Pr->SiS_SR15  = SiS310_SR15;

   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;

   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;

   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;

   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;

   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;

   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;

   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;
   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
}
#endif

bool
SiSInitPtr(struct SiS_Private *SiS_Pr)
{
   if(SiS_Pr->ChipType < SIS_315H) {
#ifdef CONFIG_FB_SIS_300
      InitTo300Pointer(SiS_Pr);
#else
      return false;
#endif
   } else {
#ifdef CONFIG_FB_SIS_315
      InitTo310Pointer(SiS_Pr);
#else
      return false;
#endif
   }
   return true;
}

/*********************************************/
/*            HELPER: Get ModeID             */
/*********************************************/

static
unsigned short
SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
  int Depth, bool FSTN, int LCDwidth, int LCDheight)
{
   unsigned short ModeIndex = 0;

   switch(HDisplay)
   {
 case 320:
  if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
  else if(VDisplay == 240) {
   if((VBFlags & CRT2_LCD) && (FSTN))
    ModeIndex = ModeIndex_320x240_FSTN[Depth];
   else
    ModeIndex = ModeIndex_320x240[Depth];
  }
  break;
 case 400:
  if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDheight >= 600))) {
   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
  }
  break;
 case 512:
  if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDheight >= 768))) {
   if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
  }
  break;
 case 640:
  if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
  break;
 case 720:
  if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
  else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
  break;
 case 768:
  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
  break;
 case 800:
  if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
  else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
  break;
 case 848:
  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
  break;
 case 856:
  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
  break;
 case 960:
  if(VGAEngine == SIS_315_VGA) {
   if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
   else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
  }
  break;
 case 1024:
  if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
  else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
  else if(VGAEngine == SIS_300_VGA) {
   if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
  }
  break;
 case 1152:
  if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
  if(VGAEngine == SIS_300_VGA) {
   if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
  }
  break;
 case 1280:
  switch(VDisplay) {
   case 720:
    ModeIndex = ModeIndex_1280x720[Depth];
    break;
   case 768:
    if(VGAEngine == SIS_300_VGA) {
     ModeIndex = ModeIndex_300_1280x768[Depth];
    } else {
     ModeIndex = ModeIndex_310_1280x768[Depth];
    }
    break;
   case 800:
    if(VGAEngine == SIS_315_VGA) {
     ModeIndex = ModeIndex_1280x800[Depth];
    }
    break;
   case 854:
    if(VGAEngine == SIS_315_VGA) {
     ModeIndex = ModeIndex_1280x854[Depth];
    }
    break;
   case 960:
    ModeIndex = ModeIndex_1280x960[Depth];
    break;
   case 1024:
    ModeIndex = ModeIndex_1280x1024[Depth];
    break;
  }
  break;
 case 1360:
  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
  if(VGAEngine == SIS_300_VGA) {
   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
  }
  break;
 case 1400:
  if(VGAEngine == SIS_315_VGA) {
   if(VDisplay == 1050) {
    ModeIndex = ModeIndex_1400x1050[Depth];
   }
  }
  break;
 case 1600:
  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
  break;
 case 1680:
  if(VGAEngine == SIS_315_VGA) {
   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
  }
  break;
 case 1920:
  if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
  else if(VGAEngine == SIS_315_VGA) {
   if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
  }
  break;
 case 2048:
  if(VDisplay == 1536) {
   if(VGAEngine == SIS_300_VGA) {
    ModeIndex = ModeIndex_300_2048x1536[Depth];
   } else {
    ModeIndex = ModeIndex_310_2048x1536[Depth];
   }
  }
  break;
   }

   return ModeIndex;
}

unsigned short
SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
  int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
  unsigned int VBFlags2)
{
   unsigned short ModeIndex = 0;

   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {

      switch(HDisplay)
      {
 case 320:
      if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
  if(VDisplay == 200) {
     if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
  } else if(VDisplay == 240) {
     if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
     else if(VGAEngine == SIS_315_VGA) {
        ModeIndex = ModeIndex_320x240_FSTN[Depth];
     }
  }
      }
      break;
 case 400:
      if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
  if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
     if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
  }
      }
      break;
 case 512:
      if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
  if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
     if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
        if(VDisplay == 384) {
           ModeIndex = ModeIndex_512x384[Depth];
        }
     }
  }
      }
      break;
 case 640:
      if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
      else if(VDisplay == 400) {
  if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
     ModeIndex = ModeIndex_640x400[Depth];
      }
      break;
 case 800:
      if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
      break;
 case 848:
      if(CustomT == CUT_PANEL848) {
         if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
      }
      break;
 case 856:
      if(CustomT == CUT_PANEL856) {
         if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
      }
      break;
 case 1024:
      if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
      else if(VGAEngine == SIS_300_VGA) {
  if((VDisplay == 600) && (LCDheight == 600)) {
     ModeIndex = ModeIndex_1024x600[Depth];
  }
      }
      break;
 case 1152:
      if(VGAEngine == SIS_300_VGA) {
  if((VDisplay == 768) && (LCDheight == 768)) {
     ModeIndex = ModeIndex_1152x768[Depth];
  }
      }
      break;
        case 1280:
      if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
      else if(VGAEngine == SIS_315_VGA) {
  if((VDisplay == 768) && (LCDheight == 768)) {
     ModeIndex = ModeIndex_310_1280x768[Depth];
  }
      }
      break;
 case 1360:
      if(VGAEngine == SIS_300_VGA) {
  if(CustomT == CUT_BARCO1366) {
     if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
  }
      }
      if(CustomT == CUT_PANEL848) {
  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
      }
      break;
 case 1400:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
      }
      break;
 case 1600:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
      }
      break;
      }

   } else if(VBFlags2 & VB2_SISBRIDGE) {

      switch(HDisplay)
      {
 case 320:
      if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
      else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
      break;
 case 400:
      if(LCDwidth >= 800 && LCDheight >= 600) {
  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
      }
      break;
 case 512:
      if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
      }
      break;
 case 640:
      if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
      else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
      break;
 case 720:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
  else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
      }
      break;
 case 768:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
      }
      break;
 case 800:
      if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
      }
      break;
 case 848:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
      }
      break;
 case 856:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
      }
      break;
 case 960:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
  else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
      }
      break;
 case 1024:
      if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
      }
      break;
 case 1152:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
      }
      break;
 case 1280:
      switch(VDisplay) {
      case 720:
  ModeIndex = ModeIndex_1280x720[Depth];
  break;
      case 768:
  if(VGAEngine == SIS_300_VGA) {
     ModeIndex = ModeIndex_300_1280x768[Depth];
  } else {
     ModeIndex = ModeIndex_310_1280x768[Depth];
  }
  break;
      case 800:
  if(VGAEngine == SIS_315_VGA) {
     ModeIndex = ModeIndex_1280x800[Depth];
  }
  break;
      case 854:
  if(VGAEngine == SIS_315_VGA) {
     ModeIndex = ModeIndex_1280x854[Depth];
  }
  break;
      case 960:
  ModeIndex = ModeIndex_1280x960[Depth];
  break;
      case 1024:
  ModeIndex = ModeIndex_1280x1024[Depth];
  break;
      }
      break;
 case 1360:
      if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
      }
      break;
 case 1400:
      if(VGAEngine == SIS_315_VGA) {
  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
     if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
  }
      }
      break;
 case 1600:
      if(VGAEngine == SIS_315_VGA) {
  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
     if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
  }
      }
      break;
#ifndef VB_FORBID_CRT2LCD_OVER_1600
 case 1680:
      if(VGAEngine == SIS_315_VGA) {
  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
     if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
  }
      }
      break;
 case 1920:
      if(VGAEngine == SIS_315_VGA) {
  if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
     if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
  }
      }
      break;
 case 2048:
      if(VGAEngine == SIS_315_VGA) {
  if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
     if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
  }
      }
      break;
#endif
      }
   }

   return ModeIndex;
}

unsigned short
SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
   unsigned int VBFlags2)
{
   unsigned short ModeIndex = 0;

   if(VBFlags2 & VB2_CHRONTEL) {

      switch(HDisplay)
      {
 case 512:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
      }
      break;
 case 640:
      if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
      else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
      break;
 case 800:
      if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
      break;
 case 1024:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
      }
      break;
      }

   } else if(VBFlags2 & VB2_SISTVBRIDGE) {

      switch(HDisplay)
      {
 case 320:
      if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
      else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
      break;
 case 400:
      if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
      break;
 case 512:
      if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
   (VBFlags & TV_HIVISION)            ||
   ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
      }
      break;
 case 640:
      if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
      else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
      break;
 case 720:
      if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
  if(VDisplay == 480) {
     ModeIndex = ModeIndex_720x480[Depth];
  } else if(VDisplay == 576) {
     if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
         ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
        ModeIndex = ModeIndex_720x576[Depth];
  }
      }
             break;
 case 768:
      if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
  if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
      ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
     if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
  }
             }
      break;
 case 800:
      if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
      else if(VDisplay == 480) {
  if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
     ModeIndex = ModeIndex_800x480[Depth];
  }
      }
      break;
 case 960:
      if(VGAEngine == SIS_315_VGA) {
  if(VDisplay == 600) {
     if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
        ModeIndex = ModeIndex_960x600[Depth];
     }
  }
      }
      break;
 case 1024:
      if(VDisplay == 768) {
  if(VBFlags2 & VB2_30xBLV) {
     ModeIndex = ModeIndex_1024x768[Depth];
  }
      } else if(VDisplay == 576) {
  if( (VBFlags & TV_HIVISION) ||
      ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
      ((VBFlags2 & VB2_30xBLV) &&
       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
     ModeIndex = ModeIndex_1024x576[Depth];
  }
      }
      break;
 case 1280:
      if(VDisplay == 720) {
  if((VBFlags & TV_HIVISION) ||
     ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
     ModeIndex = ModeIndex_1280x720[Depth];
  }
      } else if(VDisplay == 1024) {
  if((VBFlags & TV_HIVISION) ||
     ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
     ModeIndex = ModeIndex_1280x1024[Depth];
  }
      }
      break;
      }
   }
   return ModeIndex;
}

unsigned short
SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
   unsigned int VBFlags2)
{
   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;

   if(HDisplay >= 1920) return 0;

   switch(HDisplay)
   {
 case 1600:
  if(VDisplay == 1200) {
   if(VGAEngine != SIS_315_VGA) return 0;
   if(!(VBFlags2 & VB2_30xB)) return 0;
  }
  break;
 case 1680:
  if(VDisplay == 1050) {
   if(VGAEngine != SIS_315_VGA) return 0;
   if(!(VBFlags2 & VB2_30xB)) return 0;
  }
  break;
   }

   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
}


/*********************************************/
/*          HELPER: SetReg, GetReg           */
/*********************************************/

void
SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
{
 outb(index, port);
 outb(data, port + 1);
}

void
SiS_SetRegByte(SISIOADDRESS port, u8 data)
{
 outb(data, port);
}

void
SiS_SetRegShort(SISIOADDRESS port, u16 data)
{
 outw(data, port);
}

void
SiS_SetRegLong(SISIOADDRESS port, u32 data)
{
 outl(data, port);
}

u8
SiS_GetReg(SISIOADDRESS port, u8 index)
{
 outb(index, port);
 return inb(port + 1);
}

u8
SiS_GetRegByte(SISIOADDRESS port)
{
 return inb(port);
}

u16
SiS_GetRegShort(SISIOADDRESS port)
{
 return inw(port);
}

u32
SiS_GetRegLong(SISIOADDRESS port)
{
 return inl(port);
}

void
SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
{
   u8 temp;

   temp = SiS_GetReg(Port, Index);
   temp = (temp & (DataAND)) | DataOR;
   SiS_SetReg(Port, Index, temp);
}

void
SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
{
   u8 temp;

   temp = SiS_GetReg(Port, Index);
   temp &= DataAND;
   SiS_SetReg(Port, Index, temp);
}

void
SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
{
   u8 temp;

   temp = SiS_GetReg(Port, Index);
   temp |= DataOR;
   SiS_SetReg(Port, Index, temp);
}

/*********************************************/
/*      HELPER: DisplayOn, DisplayOff        */
/*********************************************/

void
SiS_DisplayOn(struct SiS_Private *SiS_Pr)
{
   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
}

void
SiS_DisplayOff(struct SiS_Private *SiS_Pr)
{
   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
}


/*********************************************/
/*        HELPER: Init Port Addresses        */
/*********************************************/

void
SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
{
   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
}

/*********************************************/
/*             HELPER: GetSysFlags           */
/*********************************************/

static void
SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
{
   unsigned char cr5f, temp1, temp2;

   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
   /* (SR11 is used for DDC and in enable/disablebridge) */
   SiS_Pr->SiS_SensibleSR11 = false;
   SiS_Pr->SiS_MyCR63 = 0x63;
   if(SiS_Pr->ChipType >= SIS_330) {
      SiS_Pr->SiS_MyCR63 = 0x53;
      if(SiS_Pr->ChipType >= SIS_661) {
         SiS_Pr->SiS_SensibleSR11 = true;
      }
   }

   /* You should use the macros, not these flags directly */

   SiS_Pr->SiS_SysFlags = 0;
   if(SiS_Pr->ChipType == SIS_650) {
      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
      if((!temp1) || (temp2)) {
  switch(cr5f) {
     case 0x80:
     case 0x90:
     case 0xc0:
        SiS_Pr->SiS_SysFlags |= SF_IsM650;
        break;
     case 0xa0:
     case 0xb0:
     case 0xe0:
        SiS_Pr->SiS_SysFlags |= SF_Is651;
        break;
  }
      } else {
  switch(cr5f) {
     case 0x90:
        temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
        switch(temp1) {
    case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
    case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
    default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
        }
        break;
     case 0xb0:
        SiS_Pr->SiS_SysFlags |= SF_Is652;
        break;
     default:
        SiS_Pr->SiS_SysFlags |= SF_IsM650;
        break;
  }
      }
   }

   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
         SiS_Pr->SiS_SysFlags |= SF_760LFB;
      }
      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
         SiS_Pr->SiS_SysFlags |= SF_760UMA;
      }
   }
}

/*********************************************/
/*         HELPER: Init PCI & Engines        */
/*********************************************/

static void
SiSInitPCIetc(struct SiS_Private *SiS_Pr)
{
   switch(SiS_Pr->ChipType) {
#ifdef CONFIG_FB_SIS_300
   case SIS_300:
   case SIS_540:
   case SIS_630:
   case SIS_730:
      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
       *     - RELOCATED VGA IO ENABLED (0x20)
       *     - MMIO ENABLED (0x01)
       * Leave other bits untouched.
       */

      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
      /*  - Enable 2D (0x40)
       *  - Enable 3D (0x02)
       *  - Enable 3D Vertex command fetch (0x10) ?
       *  - Enable 3D command parser (0x08) ?
       */

      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
      break;
#endif
#ifdef CONFIG_FB_SIS_315
   case SIS_315H:
   case SIS_315:
   case SIS_315PRO:
   case SIS_650:
   case SIS_740:
   case SIS_330:
   case SIS_661:
   case SIS_741:
   case SIS_660:
   case SIS_760:
   case SIS_761:
   case SIS_340:
   case XGI_40:
      /* See above */
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
      /*  - Enable 3D G/L transformation engine (0x80)
       *  - Enable 2D (0x40)
       *  - Enable 3D vertex command fetch (0x10)
       *  - Enable 3D command parser (0x08)
       *  - Enable 3D (0x02)
       */

      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
      break;
   case XGI_20:
   case SIS_550:
      /* See above */
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
      /* No 3D engine ! */
      /*  - Enable 2D (0x40)
       *  - disable 3D
       */

      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
      break;
#endif
   default:
      break;
   }
}

/*********************************************/
/*             HELPER: SetLVDSetc            */
/*********************************************/

static
void
SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
{
   unsigned short temp;

   SiS_Pr->SiS_IF_DEF_LVDS = 0;
   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
   SiS_Pr->SiS_IF_DEF_CONEX = 0;

   SiS_Pr->SiS_ChrontelInit = 0;

   if(SiS_Pr->ChipType == XGI_20) return;

   /* Check for SiS30x first */
   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
   if((temp == 1) || (temp == 2)) return;

   switch(SiS_Pr->ChipType) {
#ifdef CONFIG_FB_SIS_300
   case SIS_540:
   case SIS_630:
   case SIS_730:
 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
 if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
 if(temp == 3)   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
 if((temp == 4) || (temp == 5)) {
  /* Save power status (and error check) - UNUSED */
  SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
  SiS_Pr->SiS_IF_DEF_CH70xx = 1;
 }
 break;
#endif
#ifdef CONFIG_FB_SIS_315
   case SIS_550:
   case SIS_650:
   case SIS_740:
   case SIS_330:
 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
 if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
 if(temp == 3)   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
 break;
   case SIS_661:
   case SIS_741:
   case SIS_660:
   case SIS_760:
   case SIS_761:
   case SIS_340:
   case XGI_20:
   case XGI_40:
 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
 if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
 if(temp == 3)   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
 if(temp == 4)   SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
 break;
#endif
   default:
 break;
   }
}

/*********************************************/
/*          HELPER: Enable DSTN/FSTN         */
/*********************************************/

void
SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
{
   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
}

void
SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
{
   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
}

/*********************************************/
/*            HELPER: Get modeflag           */
/*********************************************/

unsigned short
SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex)
{
   if(SiS_Pr->UseCustomMode) {
      return SiS_Pr->CModeFlag;
   } else if(ModeNo <= 0x13) {
      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
   } else {
      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
}

/*********************************************/
/*        HELPER: Determine ROM usage        */
/*********************************************/

bool
SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
{
   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
   unsigned short romversoffs, romvmaj = 1, romvmin = 0;

   if(SiS_Pr->ChipType >= XGI_20) {
      /* XGI ROMs don't qualify */
      return false;
   } else if(SiS_Pr->ChipType >= SIS_761) {
      /* I very much assume 761, 340 and newer will use new layout */
      return true;
   } else if(SiS_Pr->ChipType >= SIS_661) {
      if((ROMAddr[0x1a] == 'N') &&
  (ROMAddr[0x1b] == 'e') &&
  (ROMAddr[0x1c] == 'w') &&
  (ROMAddr[0x1d] == 'V')) {
  return true;
      }
      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
      if(romversoffs) {
  if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
     romvmaj = ROMAddr[romversoffs] - '0';
     romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
  }
      }
      if((romvmaj != 0) || (romvmin >= 92)) {
  return true;
      }
   } else if(IS_SIS650740) {
      if((ROMAddr[0x1a] == 'N') &&
  (ROMAddr[0x1b] == 'e') &&
  (ROMAddr[0x1c] == 'w') &&
  (ROMAddr[0x1d] == 'V')) {
  return true;
      }
   }
   return false;
}

static void
SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
{
   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
   unsigned short romptr = 0;

   SiS_Pr->SiS_UseROM = false;
   SiS_Pr->SiS_ROMNew = false;
   SiS_Pr->SiS_PWDOffset = 0;

   if(SiS_Pr->ChipType >= XGI_20) return;

   if((ROMAddr) && (SiS_Pr->UseROM)) {
      if(SiS_Pr->ChipType == SIS_300) {
  /* 300: We check if the code starts below 0x220 by
  * checking the jmp instruction at the beginning
  * of the BIOS image.
  */

  if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
     SiS_Pr->SiS_UseROM = true;
      } else if(SiS_Pr->ChipType < SIS_315H) {
  /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
  * the others do as well
  */

  SiS_Pr->SiS_UseROM = true;
      } else {
  /* 315/330 series stick to the standard(s) */
  SiS_Pr->SiS_UseROM = true;
  if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
     SiS_Pr->SiS_EMIOffset = 14;
     SiS_Pr->SiS_PWDOffset = 17;
     SiS_Pr->SiS661LCD2TableSize = 36;
     /* Find out about LCD data table entry size */
     if((romptr = SISGETROMW(0x0102))) {
        if(ROMAddr[romptr + (32 * 16)] == 0xff)
    SiS_Pr->SiS661LCD2TableSize = 32;
        else if(ROMAddr[romptr + (34 * 16)] == 0xff)
    SiS_Pr->SiS661LCD2TableSize = 34;
        else if(ROMAddr[romptr + (36 * 16)] == 0xff)    /* 0.94, 2.05.00+ */
    SiS_Pr->SiS661LCD2TableSize = 36;
        else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
    (ROMAddr[0x6F] & 0x01) ) {     /* 2.03.00 - <2.05.00 */
    SiS_Pr->SiS661LCD2TableSize = 38;     /* UMC data layout abandoned at 2.05.00 */
    SiS_Pr->SiS_EMIOffset = 16;
    SiS_Pr->SiS_PWDOffset = 19;
        }
     }
  }
      }
   }
}

/*********************************************/
/*        HELPER: SET SEGMENT REGISTERS      */
/*********************************************/

static void
SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
{
   unsigned short temp;

   value &= 0x00ff;
   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
   temp |= (value >> 4);
   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
   temp |= (value & 0x0f);
   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
}

static void
SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
{
   unsigned short temp;

   value &= 0x00ff;
   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
   temp |= (value & 0xf0);
   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
   temp |= (value << 4);
   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
}

static void
SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
{
   SiS_SetSegRegLower(SiS_Pr, value);
   SiS_SetSegRegUpper(SiS_Pr, value);
}

static void
SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
{
   SiS_SetSegmentReg(SiS_Pr, 0);
}

static void
SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
{
   unsigned short temp = value >> 8;

   temp &= 0x07;
   temp |= (temp << 4);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
   SiS_SetSegmentReg(SiS_Pr, value);
}

static void
SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
{
   SiS_SetSegmentRegOver(SiS_Pr, 0);
}

static void
SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
{
   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
      SiS_ResetSegmentReg(SiS_Pr);
      SiS_ResetSegmentRegOver(SiS_Pr);
   }
}

/*********************************************/
/*             HELPER: GetVBType             */
/*********************************************/

static
void
SiS_GetVBType(struct SiS_Private *SiS_Pr)
{
   unsigned short flag = 0, rev = 0, nolcd = 0;
   unsigned short p4_0f, p4_25, p4_27;

   SiS_Pr->SiS_VBType = 0;

   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
      return;

   if(SiS_Pr->ChipType == XGI_20)
      return;

   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);

   if(flag > 3)
      return;

   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);

   if(flag >= 2) {
      SiS_Pr->SiS_VBType = VB_SIS302B;
   } else if(flag == 1) {
      if(rev >= 0xC0) {
  SiS_Pr->SiS_VBType = VB_SIS301C;
      } else if(rev >= 0xB0) {
  SiS_Pr->SiS_VBType = VB_SIS301B;
  /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
  nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
  if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
      } else {
  SiS_Pr->SiS_VBType = VB_SIS301;
      }
   }
   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
      if(rev >= 0xE0) {
  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
  if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
  else      SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
      } else if(rev >= 0xD0) {
  SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
   }
   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
         SiS_Pr->SiS_VBType |= VB_UMC;
      }
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
   }
}

/*********************************************/
/*           HELPER: Check RAM size          */
/*********************************************/

static bool
SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex)
{
   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;

   if(!AdapterMemSize) return true;

   if(AdapterMemSize < memorysize) return false;
   return true;
}

/*********************************************/
/*           HELPER: Get DRAM type           */
/*********************************************/

#ifdef CONFIG_FB_SIS_315
static unsigned char
SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
{
   unsigned char data;

   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
   } else {
      if(SiS_Pr->ChipType >= XGI_20) {
         /* Do I need this? SR17 seems to be zero anyway... */
  data = 0;
      } else if(SiS_Pr->ChipType >= SIS_340) {
  /* TODO */
  data = 0;
      } else if(SiS_Pr->ChipType >= SIS_661) {
  if(SiS_Pr->SiS_ROMNew) {
     data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
  } else {
     data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
  }
      } else if(IS_SIS550650740) {
  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
      } else { /* 315, 330 */
  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
  if(SiS_Pr->ChipType == SIS_330) {
     if(data > 1) {
        switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
        case 0x00: data = 1; break;
        case 0x10: data = 3; break;
        case 0x20: data = 3; break;
        case 0x30: data = 2; break;
        }
     } else {
        data = 0;
     }
  }
      }
   }

   return data;
}

static unsigned short
SiS_GetMCLK(struct SiS_Private *SiS_Pr)
{
   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
   unsigned short index;

   index = SiS_Get310DRAMType(SiS_Pr);
   if(SiS_Pr->ChipType >= SIS_661) {
      if(SiS_Pr->SiS_ROMNew) {
  return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
      }
      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
   } else if(index >= 4) {
      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
   } else {
      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
   }
}
#endif

/*********************************************/
/*           HELPER: ClearBuffer             */
/*********************************************/

static void
SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
   unsigned int   memsize = SiS_Pr->VideoMemorySize;
   unsigned short SISIOMEMTYPE *pBuffer;
   int i;

   if(!memaddr || !memsize) return;

   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
      if(ModeNo > 0x13) {
  memset_io(memaddr, 0, memsize);
      } else {
  pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
  for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
      }
   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
   } else {
      memset_io(memaddr, 0, 0x8000);
   }
}

/*********************************************/
/*           HELPER: SearchModeID            */
/*********************************************/

bool
SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
  unsigned short *ModeIdIndex)
{
   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;

   if((*ModeNo) <= 0x13) {

      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;

      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
  if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
  if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
      }

      if((*ModeNo) == 0x07) {
   if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
   /* else 350 lines */
      }
      if((*ModeNo) <= 0x03) {
  if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
  if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
  /* else 350 lines  */
      }
      /* else 200 lines  */

   } else {

      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
  if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
  if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
      }

   }
   return true;
}

/*********************************************/
/*            HELPER: GetModePtr             */
/*********************************************/

unsigned short
SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
   unsigned short index;

   if(ModeNo <= 0x13) {
      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
   } else {
      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
      else index = 0x0F;
   }
   return index;
}

/*********************************************/
/*         HELPERS: Get some indices         */
/*********************************************/

unsigned short
SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
{
   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
      if(UseWide == 1) {
         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
      } else {
         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
      }
   } else {
      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
   }
}

unsigned short
SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
{
   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
      if(UseWide == 1) {
         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
      } else {
         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
      }
   } else {
      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
   }
}

/*********************************************/
/*           HELPER: LowModeTests            */
/*********************************************/

static bool
SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
   unsigned short temp, temp1, temp2;

   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
      return true;
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
   if((SiS_Pr->ChipType >= SIS_315H) ||
      (SiS_Pr->ChipType == SIS_300)) {
      if(temp2 == 0x55) return false;
      else return true;
   } else {
      if(temp2 != 0x55) return true;
      else {
  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
  return false;
      }
   }
}

static void
SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
      SiS_Pr->SiS_SetFlag |= LowModeTests;
   }
}

/*********************************************/
/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
/*********************************************/

static void
SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
{
   if(IS_SIS650) {
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
   } else if(IS_SIS661741660760) {
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
      if(!SiS_Pr->SiS_ROMNew) {
  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
      }
   }
}

static void
SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
{
#if 0 /* This locks some CRTC registers. We don't want that. */
   unsigned short temp1 = 0, temp2 = 0;

   if(IS_SIS661741660760) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
         temp1 = 0xa0; temp2 = 0x08;
      }
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
   }
#endif
}

static void
SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
{
   /* Enable CRT1 gating */
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
#if 0
   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
      }
   }
#endif
}

/*********************************************/
/*           HELPER: GetColorDepth           */
/*********************************************/

unsigned short
SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex)
{
   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
   unsigned short modeflag;
   short index;

   /* Do NOT check UseCustomMode, will skrew up FIFO */
   if(ModeNo == 0xfe) {
      modeflag = SiS_Pr->CModeFlag;
   } else if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }

   index = (modeflag & ModeTypeMask) - ModeEGA;
   if(index < 0) index = 0;
   return ColorDepth[index];
}

/*********************************************/
/*             HELPER: GetOffset             */
/*********************************************/

unsigned short
SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex, unsigned short RRTI)
{
   unsigned short xres, temp, colordepth, infoflag;

   if(SiS_Pr->UseCustomMode) {
      infoflag = SiS_Pr->CInfoFlag;
      xres = SiS_Pr->CHDisplay;
   } else {
      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
   }

   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);

   temp = xres / 16;
   if(infoflag & InterlaceMode) temp <<= 1;
   temp *= colordepth;
   if(xres % 16) temp += (colordepth >> 1);

   return temp;
}

/*********************************************/
/*                   SEQ                     */
/*********************************************/

static void
SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
   unsigned char SRdata;
   int i;

   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);

   /* or "display off"  */
   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;

   /* determine whether to force x8 dotclock */
   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {

      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;

   }

   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);

   for(i = 2; i <= 4; i++) {
      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
   }
}

/*********************************************/
/*                  MISC                     */
/*********************************************/

static void
SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
   unsigned char Miscdata;

   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;

   if(SiS_Pr->ChipType < SIS_661) {
      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
    Miscdata |= 0x0C;
  }
      }
   }

   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
}

/*********************************************/
/*                  CRTC                     */
/*********************************************/

static void
SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
   unsigned char  CRTCdata;
   unsigned short i;

   /* Unlock CRTC */
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);

   for(i = 0; i <= 0x18; i++) {
      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
   }

   if(SiS_Pr->ChipType >= SIS_661) {
      SiS_OpenCRTC(SiS_Pr);
      for(i = 0x13; i <= 0x14; i++) {
  CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
  SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
      }
   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
         (SiS_Pr->ChipType == SIS_730) )  &&
       (SiS_Pr->ChipRevision >= 0x30) ) {
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
     SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
  }
      }
   }
}

/*********************************************/
/*                   ATT                     */
/*********************************************/

static void
SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
   unsigned char  ARdata;
   unsigned short i;

   for(i = 0; i <= 0x13; i++) {
      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];

      if(i == 0x13) {
  /* Pixel shift. If screen on LCD or TV is shifted left or right,
  * this might be the cause.
  */

  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
  }
  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
     if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
        }
     }
  }
  if(SiS_Pr->ChipType >= SIS_661) {
     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
     }
  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
     if(SiS_Pr->ChipType >= SIS_315H) {
        if(IS_SIS550650740660) {
    /* 315, 330 don't do this */
    if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
    } else {
       ARdata = 0;
    }
        }
     } else {
        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
     }
  }
      }
      SiS_GetRegByte(SiS_Pr->SiS_P3da);  /* reset 3da  */
      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index  */
      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data   */
   }

   SiS_GetRegByte(SiS_Pr->SiS_P3da);  /* reset 3da  */
   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index  */
   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data   */

   SiS_GetRegByte(SiS_Pr->SiS_P3da);
   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute  */
   SiS_GetRegByte(SiS_Pr->SiS_P3da);
}

/*********************************************/
/*                   GRC                     */
/*********************************************/

static void
SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
   unsigned char  GRdata;
   unsigned short i;

   for(i = 0; i <= 0x08; i++) {
      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
   }

   if(SiS_Pr->SiS_ModeType > ModeVGA) {
      /* 256 color disable */
      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
   }
}

/*********************************************/
/*          CLEAR EXTENDED REGISTERS         */
/*********************************************/

static void
SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
   unsigned short i;

   for(i = 0x0A; i <= 0x0E; i++) {
      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
   }

   if(SiS_Pr->ChipType >= SIS_315H) {
      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
      if(ModeNo <= 0x13) {
  if(ModeNo == 0x06 || ModeNo >= 0x0e) {
     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
  }
      }
   }
}

/*********************************************/
/*                 RESET VCLK                */
/*********************************************/

static void
SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
{
   if(SiS_Pr->ChipType >= SIS_315H) {
      if(SiS_Pr->ChipType < SIS_661) {
  if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
      }
   } else {
      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
  (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
  return;
      }
   }

   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
}

/*********************************************/
/*                  SYNC                     */
/*********************************************/

static void
SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
{
   unsigned short sync;

   if(SiS_Pr->UseCustomMode) {
      sync = SiS_Pr->CInfoFlag >> 8;
   } else {
      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
   }

   sync &= 0xC0;
   sync |= 0x2f;
   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
}

/*********************************************/
/*                  CRTC/2                   */
/*********************************************/

static void
SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex, unsigned short RRTI)
{
   unsigned short temp, i, j, modeflag;
   unsigned char  *crt1data = NULL;

   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);

   if(SiS_Pr->UseCustomMode) {

      crt1data = &SiS_Pr->CCRT1CRTC[0];

   } else {

      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);

      /* Alternate for 1600x1200 LCDA */
      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;

      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];

   }

   /* unlock cr0-7 */
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);

   for(i = 0, j = 0; i <= 7; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
   }
   for(j = 0x10; i <= 10; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
   }
   for(j = 0x15; i <= 12; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
   }
   for(j = 0x0A; i <= 15; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
   }

   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);

   temp = (crt1data[16] & 0x01) << 5;
   if(modeflag & DoubleScanMode) temp |= 0x80;
   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);

   if(SiS_Pr->SiS_ModeType > ModeVGA) {
      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
   }

#ifdef CONFIG_FB_SIS_315
   if(SiS_Pr->ChipType == XGI_20) {
      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
      if(!(temp = crt1data[5] & 0x1f)) {
         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
      }
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
      temp = (crt1data[16] >> 5) + 3;
      if(temp > 7) temp -= 7;
      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
   }
#endif
}

/*********************************************/
/*               OFFSET & PITCH              */
/*********************************************/
/*  (partly overruled by SetPitch() in XF86) */
/*********************************************/

static void
SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex, unsigned short RRTI)
{
   unsigned short temp, DisplayUnit, infoflag;

   if(SiS_Pr->UseCustomMode) {
      infoflag = SiS_Pr->CInfoFlag;
   } else {
      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
   }

   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);

   temp = (DisplayUnit >> 8) & 0x0f;
   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);

   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);

   if(infoflag & InterlaceMode) DisplayUnit >>= 1;

   DisplayUnit <<= 5;
   temp = (DisplayUnit >> 8) + 1;
   if(DisplayUnit & 0xff) temp++;
   if(SiS_Pr->ChipType == XGI_20) {
      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
   }
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
}

/*********************************************/
/*                  VCLK                     */
/*********************************************/

static void
SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  unsigned short ModeIdIndex, unsigned short RRTI)
{
   unsigned short index = 0, clka, clkb;

   if(SiS_Pr->UseCustomMode) {
      clka = SiS_Pr->CSR2B;
      clkb = SiS_Pr->CSR2C;
   } else {
      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
  (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.21 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge