patch-2.4.22 linux-2.4.22/drivers/video/sis/init.c

Next file: linux-2.4.22/drivers/video/sis/init.h
Previous file: linux-2.4.22/drivers/video/sis/310vtbl.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/video/sis/init.c linux-2.4.22/drivers/video/sis/init.c
@@ -1,24 +1,16 @@
 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init.c,v 1.3 2002/24/04 01:16:16 dawes Exp $ */
 /*
- * Mode switching code (CRT1 section) for SiS 300/540/630/730/315/550/650/740/330
+ * Mode switching code (CRT1 section) for SiS 300/540/630/730/315/550/650/740/330/660
  * (Universal module for Linux kernel framebuffer and XFree86 4.x)
  *
  * Assembler-To-C translation
- * Copyright 2002 by Thomas Winischhofer <thomas@winischhofer.net>
- * Minor parts Copyright SiS, Inc.
+ * Copyright 2002, 2003 by Thomas Winischhofer <thomas@winischhofer.net>
+ * Formerly based on non-functional code-fragements by SiS, Inc.
  *
- * Based on BIOS
- *     1.10.07, 1.10a for 650/CH7019
- *     1.11.21a for 740/CH7019
- *     1.11.05 for 650/LVDS (w/o Chrontel)
- *     1.07.1b, 1.11.6s, 1.11.6w, 1.11.7w, 1.11.8r for 650/301(B/LV)
- *     2.04.50 (I) and 2.04.5c (II) for 630/301(B)
- *     2.06.50 for 630/301B (dual VGA)
- *     2.02.3b, 2.03.02, 2.04.5c, 2.07a and 2.08.b3 for 630/LVDS/LVDS+CH7005
- *     2.04.5c, 2.04.6c for 730+LVDS+CH7005
- *     1.09b for 315/301(B)
- *     1.16.51 for 300+301LV (ECS A907)
- *     1.01.03 for 330 (Xabre 400)
+ * If distributed as part of the linux kernel, the contents of this file
+ * is entirely covered by the GPL.
+ *
+ * Otherwise, the following terms apply:
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -61,12 +53,12 @@
 #ifdef LINUX_XF86
 BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
                        ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
-DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn);
-#ifdef SISDUALHEAD /* TW: For dual head */
+DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi);
+#ifdef SISDUALHEAD
 BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
                        ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
 BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
-                       ScrnInfoPtr pScrn, DisplayModePtr mode);
+                       ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
 #endif /* dual head */
 #endif /* linux_xf86 */
 
@@ -90,49 +82,199 @@
 static ULONG GetDRAMSize(SiS_Private *SiS_Pr,
                          PSIS_HW_DEVICE_INFO HwDeviceExtension);
 
-static void DelaySeconds(int seconds);
-void SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code);
-
 static void
-DelaySeconds(int seconds)
-{
-  int i;
-#ifdef WIN2000
-  int j;
-#endif
-
-  for (i=0;i<seconds;i++) {
-#ifdef TC
-    delay(1000);
-#endif
-
-#ifdef WIN2000
-    for (j=0;j<20000;j++)
-      VideoPortStallExecution(50);
-#endif
-
-#ifdef WINCE_HEADER
-#endif
-
-#ifdef LINUX_KERNEL
-#endif
-  }
-}
-
-void
-SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code)
+InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
 {
-  OutPortByte(0x80, code);
-  DelaySeconds(0x3);
+   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
+   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
+   SiS_Pr->SiS_StandTable    = SiS_StandTable;
+   if(HwDeviceExtension->jChipType < SIS_315H) {
+      SiS_StandTable[0x04].CRTC[4] = 0x2b;
+      SiS_StandTable[0x05].CRTC[4] = 0x2b;
+      SiS_StandTable[0x06].CRTC[4] = 0x54;
+      SiS_StandTable[0x06].CRTC[5] = 0x80;
+      SiS_StandTable[0x0d].CRTC[4] = 0x2b;
+      SiS_StandTable[0x0e].CRTC[4] = 0x54;
+      SiS_StandTable[0x0e].CRTC[5] = 0x80;
+      SiS_StandTable[0x11].CRTC[4] = 0x54;
+      SiS_StandTable[0x11].CRTC[5] = 0x80;
+      SiS_StandTable[0x11].CRTC[16] = 0x83;
+      SiS_StandTable[0x11].CRTC[17] = 0x85;
+      SiS_StandTable[0x12].CRTC[4] = 0x54;
+      SiS_StandTable[0x12].CRTC[5] = 0x80;
+      SiS_StandTable[0x12].CRTC[16] = 0x83;
+      SiS_StandTable[0x12].CRTC[17] = 0x85;
+      SiS_StandTable[0x13].CRTC[5] = 0xa0;
+      SiS_StandTable[0x17].CRTC[5] = 0xa0;
+      SiS_StandTable[0x1a].CRTC[4] = 0x54;
+      SiS_StandTable[0x1a].CRTC[5] = 0x80;
+      SiS_StandTable[0x1a].CRTC[16] = 0xea;
+      SiS_StandTable[0x1a].CRTC[17] = 0x8c;
+      SiS_StandTable[0x1b].CRTC[4] = 0x54;
+      SiS_StandTable[0x1b].CRTC[5] = 0x80;
+      SiS_StandTable[0x1b].CRTC[16] = 0xea;
+      SiS_StandTable[0x1b].CRTC[17] = 0x8c;
+      SiS_StandTable[0x1c].CRTC[4] = 0x54;
+      SiS_StandTable[0x1c].CRTC[5] = 0x80;
+   } else {
+      SiS_StandTable[0x04].CRTC[4] = 0x2c;
+      SiS_StandTable[0x05].CRTC[4] = 0x2c;
+      SiS_StandTable[0x06].CRTC[4] = 0x55;
+      SiS_StandTable[0x06].CRTC[5] = 0x81;
+      SiS_StandTable[0x0d].CRTC[4] = 0x2c;
+      SiS_StandTable[0x0e].CRTC[4] = 0x55;
+      SiS_StandTable[0x0e].CRTC[5] = 0x81;
+      SiS_StandTable[0x11].CRTC[4] = 0x55;
+      SiS_StandTable[0x11].CRTC[5] = 0x81;
+      SiS_StandTable[0x11].CRTC[16] = 0x82;
+      SiS_StandTable[0x11].CRTC[17] = 0x84;
+      SiS_StandTable[0x12].CRTC[4] = 0x55;
+      SiS_StandTable[0x12].CRTC[5] = 0x81;
+      SiS_StandTable[0x12].CRTC[16] = 0x82;
+      SiS_StandTable[0x12].CRTC[17] = 0x84;
+      SiS_StandTable[0x13].CRTC[5] = 0xb1;
+      SiS_StandTable[0x17].CRTC[5] = 0xb1;
+      SiS_StandTable[0x1a].CRTC[4] = 0x55;
+      SiS_StandTable[0x1a].CRTC[5] = 0x81;
+      SiS_StandTable[0x1a].CRTC[16] = 0xe9;
+      SiS_StandTable[0x1a].CRTC[17] = 0x8b;
+      SiS_StandTable[0x1b].CRTC[4] = 0x55;
+      SiS_StandTable[0x1b].CRTC[5] = 0x81;
+      SiS_StandTable[0x1b].CRTC[16] = 0xe9;
+      SiS_StandTable[0x1b].CRTC[17] = 0x8b;
+      SiS_StandTable[0x1c].CRTC[4] = 0x55;
+      SiS_StandTable[0x1c].CRTC[5] = 0x81;
+   }
+
+   SiS_Pr->SiS_NTSCPhase    = SiS_NTSCPhase;
+   SiS_Pr->SiS_PALPhase     = SiS_PALPhase;
+   SiS_Pr->SiS_NTSCPhase2   = SiS_NTSCPhase2;
+   SiS_Pr->SiS_PALPhase2    = SiS_PALPhase2;
+   SiS_Pr->SiS_PALMPhase    = SiS_PALMPhase;
+   SiS_Pr->SiS_PALNPhase    = SiS_PALNPhase;
+   SiS_Pr->SiS_PALMPhase2   = SiS_PALMPhase2;
+   SiS_Pr->SiS_PALNPhase2   = SiS_PALNPhase2;
+   SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase;
+
+   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_HiTVTextTiming = SiS_HiTVTextTiming;
+   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
+   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
+   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
+   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
+
+   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_St1HiTVData;  */
+   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
+   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
+
+   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
+   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
+
+   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
+   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
+   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
+   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
+   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
+   SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050;
+   SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200;
+   SiS_Pr->SiS_ExtLCD1280x768Data   = SiS_ExtLCD1280x768Data;
+   SiS_Pr->SiS_StLCD1280x768Data    = SiS_StLCD1280x768Data;
+   SiS_Pr->SiS_NoScaleData1280x768  = SiS_NoScaleData1280x768;
+   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
+
+   SiS_Pr->SiS_LVDS320x480Data_1   = SiS_LVDS320x480Data_1;
+   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
+   SiS_Pr->SiS_LVDS800x600Data_2   = SiS_LVDS800x600Data_2;
+   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
+   SiS_Pr->SiS_LVDS1024x768Data_2  = SiS_LVDS1024x768Data_2;
+   SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1;
+   SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2;
+   SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1;
+   SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2;
+   SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1;
+   SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2;
+   SiS_Pr->SiS_LVDS1280x768Data_1  = SiS_LVDS1280x768Data_1;
+   SiS_Pr->SiS_LVDS1280x768Data_2  = SiS_LVDS1280x768Data_2;
+   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
+   SiS_Pr->SiS_LVDS1024x600Data_2  = SiS_LVDS1024x600Data_2;
+   SiS_Pr->SiS_LVDS1152x768Data_1  = SiS_LVDS1152x768Data_1;
+   SiS_Pr->SiS_LVDS1152x768Data_2  = SiS_LVDS1152x768Data_2;
+   SiS_Pr->SiS_LVDSXXXxXXXData_1   = SiS_LVDSXXXxXXXData_1;
+   SiS_Pr->SiS_LVDS1280x960Data_1  = SiS_LVDS1280x960Data_1;
+   SiS_Pr->SiS_LVDS1280x960Data_2  = SiS_LVDS1280x960Data_2;
+   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
+   SiS_Pr->SiS_LVDS1280x960Data_1  = SiS_LVDS1280x1024Data_1;
+   SiS_Pr->SiS_LVDS1280x960Data_2  = SiS_LVDS1280x1024Data_2;
+   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
+   SiS_Pr->SiS_LVDS640x480Data_2   = SiS_LVDS640x480Data_2;
+
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
+
+   SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1;
+   SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2;
+   SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1;
+   SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2;
+   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
+   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
+
+   SiS_Pr->LVDS1024x768Des_1  = SiS_PanelType1076_1;
+   SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1;
+   SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1;
+   SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1;
+   SiS_Pr->LVDS1024x768Des_2  = SiS_PanelType1076_2;
+   SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2;
+   SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2;
+   SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2;
+
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2;
+
+   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
+   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
+   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
+   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+
+   SiS_Pr->SiS_LVDSCRT11280x768_1    = SiS_LVDSCRT11280x768_1;
+   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
+   SiS_Pr->SiS_LVDSCRT11152x768_1    = SiS_LVDSCRT11152x768_1;
+   SiS_Pr->SiS_LVDSCRT11280x768_1_H  = SiS_LVDSCRT11280x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
+   SiS_Pr->SiS_LVDSCRT11152x768_1_H  = SiS_LVDSCRT11152x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x768_2    = SiS_LVDSCRT11280x768_2;
+   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
+   SiS_Pr->SiS_LVDSCRT11152x768_2    = SiS_LVDSCRT11152x768_2;
+   SiS_Pr->SiS_LVDSCRT11280x768_2_H  = SiS_LVDSCRT11280x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11152x768_2_H  = SiS_LVDSCRT11152x768_2_H;
+   SiS_Pr->SiS_LVDSCRT1320x480_1     = SiS_LVDSCRT1320x480_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS_LVDSCRT1XXXxXXX_1_H;
+   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
+   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
+   SiS_Pr->SiS_LVDSCRT1640x480_2     = SiS_LVDSCRT1640x480_2;
+   SiS_Pr->SiS_LVDSCRT1640x480_2_H   = SiS_LVDSCRT1640x480_2_H;
+   SiS_Pr->SiS_LVDSCRT1640x480_3     = SiS_LVDSCRT1640x480_3;
+   SiS_Pr->SiS_LVDSCRT1640x480_3_H   = SiS_LVDSCRT1640x480_3_H;
 }
 
 #ifdef SIS300
 static void
 InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
 {
+   InitCommonPointer(SiS_Pr, HwDeviceExtension);
+
    SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS300_SModeIDTable;
    SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable;
-   SiS_Pr->SiS_StandTable    = (SiS_StandTableStruct *)SiS300_StandTable;
    SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS300_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS300_RefIndex;
    SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS300_CRT1Table;
@@ -141,15 +283,12 @@
    } else {
       SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */
    }
+#ifdef LINUXBIOS
    SiS_Pr->SiS_ECLKData      = (SiS_ECLKDataStruct *)SiS300_ECLKData;
+#endif
    SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS300_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
    SiS_Pr->SiS_ScreenOffset  = SiS300_ScreenOffset;
-   SiS_Pr->SiS_StResInfo     = (SiS_StResInfoStruct *)SiS300_StResInfo;
-   SiS_Pr->SiS_ModeResInfo   = (SiS_ModeResInfoStruct *)SiS300_ModeResInfo;
-
-   SiS_Pr->pSiS_OutputSelect = &SiS300_OutputSelect;
-   SiS_Pr->pSiS_SoftSetting  = &SiS300_SoftSetting;
 
    SiS_Pr->SiS_SR15  = SiS300_SR15;
 
@@ -178,15 +317,6 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS300_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_NTSCPhase  = SiS300_NTSCPhase;
-   SiS_Pr->SiS_PALPhase   = SiS300_PALPhase;
-   SiS_Pr->SiS_NTSCPhase2 = SiS300_NTSCPhase2;
-   SiS_Pr->SiS_PALPhase2  = SiS300_PALPhase2;
-   SiS_Pr->SiS_PALMPhase  = SiS300_PALMPhase;
-   SiS_Pr->SiS_PALNPhase  = SiS300_PALNPhase;
-   SiS_Pr->SiS_PALMPhase2 = SiS300_PALMPhase2;
-   SiS_Pr->SiS_PALNPhase2 = SiS300_PALNPhase2;
-
    SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data;
    SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data;
    SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data;
@@ -195,69 +325,18 @@
    SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data;
    SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768;
    SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024;
-   SiS_Pr->SiS_LCD1280x960Data      = (SiS_LCDDataStruct *)SiS300_LCD1280x960Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = (SiS_LCDDataStruct *)SiS300_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = (SiS_LCDDataStruct *)SiS300_ExtLCD1600x1200Data;
-   SiS_Pr->SiS_StLCD1400x1050Data   = (SiS_LCDDataStruct *)SiS300_StLCD1400x1050Data;
-   SiS_Pr->SiS_StLCD1600x1200Data   = (SiS_LCDDataStruct *)SiS300_StLCD1600x1200Data;
-   SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS300_NoScaleData1400x1050;
-   SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS300_NoScaleData1600x1200;
-   SiS_Pr->SiS_NoScaleData          = (SiS_LCDDataStruct *)SiS300_NoScaleData;
-
-   SiS_Pr->SiS_StPALData   = (SiS_TVDataStruct *)SiS300_StPALData;
-   SiS_Pr->SiS_ExtPALData  = (SiS_TVDataStruct *)SiS300_ExtPALData;
-   SiS_Pr->SiS_StNTSCData  = (SiS_TVDataStruct *)SiS300_StNTSCData;
-   SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS300_ExtNTSCData;
-/* SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS300_St1HiTVData;  */
-   SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS300_St2HiTVData;
-   SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS300_ExtHiTVData;
-
-   SiS_Pr->SiS_NTSCTiming     = SiS300_NTSCTiming;
-   SiS_Pr->SiS_PALTiming      = SiS300_PALTiming;
-   SiS_Pr->SiS_HiTVSt1Timing  = SiS300_HiTVSt1Timing;
-   SiS_Pr->SiS_HiTVSt2Timing  = SiS300_HiTVSt2Timing;
-   SiS_Pr->SiS_HiTVTextTiming = SiS300_HiTVTextTiming;
-   SiS_Pr->SiS_HiTVGroup3Data = SiS300_HiTVGroup3Data;
-   SiS_Pr->SiS_HiTVGroup3Simu = SiS300_HiTVGroup3Simu;
-   SiS_Pr->SiS_HiTVGroup3Text = SiS300_HiTVGroup3Text;
 
    SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
    SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS;
 
-   SiS_Pr->SiS_LVDS800x600Data_1   = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_1;
-   SiS_Pr->SiS_LVDS800x600Data_2   = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_2;
-   SiS_Pr->SiS_LVDS1024x768Data_1  = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_1;
-   SiS_Pr->SiS_LVDS1024x768Data_2  = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_2;
-   SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1;
-   SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2;
-   SiS_Pr->SiS_LVDS1280x960Data_1  = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1;
-   SiS_Pr->SiS_LVDS1280x960Data_2  = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2;
-   SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_1;
-   SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_2;
-   SiS_Pr->SiS_LVDS1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1600x1200Data_1;
-   SiS_Pr->SiS_LVDS1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1600x1200Data_2;
-   SiS_Pr->SiS_LVDS1280x768Data_1  = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_1;
-   SiS_Pr->SiS_LVDS1280x768Data_2  = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_2;
-   SiS_Pr->SiS_LVDS1024x600Data_1  = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_1;
-   SiS_Pr->SiS_LVDS1024x600Data_2  = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_2;
-   SiS_Pr->SiS_LVDS1152x768Data_1  = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_1;
-   SiS_Pr->SiS_LVDS1152x768Data_2  = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_2;
-   SiS_Pr->SiS_LVDSXXXxXXXData_1   = (SiS_LVDSDataStruct *)SiS300_LVDSXXXxXXXData_1;
-   SiS_Pr->SiS_LVDS320x480Data_1   = (SiS_LVDSDataStruct *)SiS300_LVDS320x480Data_1;
-   SiS_Pr->SiS_LVDS640x480Data_1   = (SiS_LVDSDataStruct *)SiS300_LVDS640x480Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_2;
-   SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_1;
-   SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_2;
-   SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData;
    SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;
    SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData; /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData; /* not supported on 300 series */
+   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 = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;  /* not supported on 300 series */
    SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;  /* not supported on 300 series */
    SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData;
+
    SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1;
    SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1;
    SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1;
@@ -290,32 +369,28 @@
    SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2;
    SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2;
    SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2;
-   SiS_Pr->SiS_PanelTypeNS_1 = (SiS_LVDSDesStruct *)SiS300_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = (SiS_LVDSDesStruct *)SiS300_PanelTypeNS_2;
-   SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = (SiS_LVDSDesStruct *)SiS300_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = (SiS_LVDSDesStruct *)SiS300_CHTVOPALDesData;
+
+   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a;
+      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a;
+   }
+   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b;
+      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b;
+   }
+
    SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1;
    SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1;
    SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11024x600_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1;
-   SiS_Pr->SiS_LVDSCRT11152x768_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1;
    SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H;
    SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H;
    SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1_H;
    SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2;
    SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2;
    SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11024x600_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2;
-   SiS_Pr->SiS_LVDSCRT11152x768_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2;
    SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H;
    SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H;
    SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2_H;
    SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC;
    SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC;
    SiS_Pr->SiS_CHTVCRT1UPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL;
@@ -340,7 +415,6 @@
    SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
 
-   /* TW: New from 300/301LV BIOS */
    SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1;
    SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1;
    SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1;
@@ -354,7 +428,7 @@
    SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3;
    SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3;
 
-   /* TW: LCDResInfo will on 300 series be translated to 310/325 series definitions */
+   /* TW: LCDResInfo will on 300 series be translated to 315 series definitions */
    SiS_Pr->SiS_Panel320x480   = Panel_320x480;
    SiS_Pr->SiS_Panel640x480   = Panel_640x480;
    SiS_Pr->SiS_Panel800x600   = Panel_800x600;
@@ -363,13 +437,17 @@
    SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
    SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
    SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1600x1200 = 16;  		/* TW: Something illegal */
-   SiS_Pr->SiS_Panel1400x1050 = 16;  		/* TW: Something illegal */
-   SiS_Pr->SiS_Panel1152x864  = 16;   		/* TW: Something illegal */
-   SiS_Pr->SiS_Panel1280x768  = 16;   		/* TW: Something illegal */
+   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
+   SiS_Pr->SiS_Panel1600x1200 = 255;  		/* TW: Something illegal */
+   SiS_Pr->SiS_Panel1400x1050 = 255;  		/* TW: Something illegal */
+   SiS_Pr->SiS_Panel640x480_2 = 255;  		/* TW: Something illegal */
+   SiS_Pr->SiS_Panel640x480_3 = 255;  		/* TW: Something illegal */
+   SiS_Pr->SiS_Panel1152x864  = 255;   		/* TW: Something illegal */
    SiS_Pr->SiS_PanelMax       = Panel_320x480;     /* TW: highest value */
    SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;     /* TW: Lowest value LVDS */
    SiS_Pr->SiS_PanelMin301    = Panel_1024x768;    /* TW: lowest value 301 */
+   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
+   SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366;
 }
 #endif
 
@@ -377,29 +455,33 @@
 static void
 InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
 {
+   InitCommonPointer(SiS_Pr, HwDeviceExtension);
+
    SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS310_SModeIDTable;
-   SiS_Pr->SiS_StandTable    = (SiS_StandTableStruct *)SiS310_StandTable;
    SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS310_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS310_RefIndex;
    SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS310_CRT1Table;
    /* TW: MCLK is different */
-   if(HwDeviceExtension->jChipType == SIS_330) {
+#ifdef LINUXBIOS
+   if(HwDeviceExtension->jChipType == SIS_660) {
+      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660;  /* 660 */
+   } else if(HwDeviceExtension->jChipType == SIS_330) {
+#endif
       SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330;  /* 330 */
+#ifdef LINUXBIOS
    } else if(HwDeviceExtension->jChipType > SIS_315PRO) {
       SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650;  /* 550, 650, 740 */
    } else {
       SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315;  /* 315 */
    }
+#endif
    SiS_Pr->SiS_MCLKData_1    = (SiS_MCLKDataStruct *)SiS310_MCLKData_1;
+#ifdef LINUXBIOS
    SiS_Pr->SiS_ECLKData      = (SiS_ECLKDataStruct *)SiS310_ECLKData;
+#endif
    SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS310_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData;
    SiS_Pr->SiS_ScreenOffset  = SiS310_ScreenOffset;
-   SiS_Pr->SiS_StResInfo     = (SiS_StResInfoStruct *)SiS310_StResInfo;
-   SiS_Pr->SiS_ModeResInfo   = (SiS_ModeResInfoStruct *)SiS310_ModeResInfo;
-
-   SiS_Pr->pSiS_OutputSelect = &SiS310_OutputSelect;
-   SiS_Pr->pSiS_SoftSetting  = &SiS310_SoftSetting;
 
    SiS_Pr->SiS_SR15  = SiS310_SR15;
 
@@ -428,16 +510,6 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS310_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_NTSCPhase    = SiS310_NTSCPhase;
-   SiS_Pr->SiS_PALPhase     = SiS310_PALPhase;
-   SiS_Pr->SiS_NTSCPhase2   = SiS310_NTSCPhase2;
-   SiS_Pr->SiS_PALPhase2    = SiS310_PALPhase2;
-   SiS_Pr->SiS_PALMPhase    = SiS310_PALMPhase;
-   SiS_Pr->SiS_PALNPhase    = SiS310_PALNPhase;
-   SiS_Pr->SiS_PALMPhase2   = SiS310_PALMPhase2;
-   SiS_Pr->SiS_PALNPhase2   = SiS310_PALNPhase2;
-   SiS_Pr->SiS_SpecialPhase = SiS310_SpecialPhase;
-
    SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data;
    SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data;
    SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data;
@@ -446,66 +518,10 @@
    SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data;
    SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768;
    SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024;
-   SiS_Pr->SiS_LCD1280x960Data      = (SiS_LCDDataStruct *)SiS310_LCD1280x960Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = (SiS_LCDDataStruct *)SiS310_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = (SiS_LCDDataStruct *)SiS310_ExtLCD1600x1200Data;
-   SiS_Pr->SiS_ExtLCD1280x768Data   = (SiS_LCDDataStruct *)SiS310_ExtLCD1280x768Data;
-   SiS_Pr->SiS_StLCD1400x1050Data   = (SiS_LCDDataStruct *)SiS310_StLCD1400x1050Data;
-   SiS_Pr->SiS_StLCD1600x1200Data   = (SiS_LCDDataStruct *)SiS310_StLCD1600x1200Data;
-   SiS_Pr->SiS_StLCD1280x768Data    = (SiS_LCDDataStruct *)SiS310_StLCD1280x768Data;
-   SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS310_NoScaleData1400x1050;
-   SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS310_NoScaleData1600x1200;
-   SiS_Pr->SiS_NoScaleData1280x768  = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x768;
-   SiS_Pr->SiS_NoScaleData          = (SiS_LCDDataStruct *)SiS310_NoScaleData;
-
-   SiS_Pr->SiS_StPALData   = (SiS_TVDataStruct *)SiS310_StPALData;
-   SiS_Pr->SiS_ExtPALData  = (SiS_TVDataStruct *)SiS310_ExtPALData;
-   SiS_Pr->SiS_StNTSCData  = (SiS_TVDataStruct *)SiS310_StNTSCData;
-   SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS310_ExtNTSCData;
-/* SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS310_St1HiTVData;  */
-   SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS310_St2HiTVData;
-   SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS310_ExtHiTVData;
-
-   SiS_Pr->SiS_NTSCTiming     = SiS310_NTSCTiming;
-   SiS_Pr->SiS_PALTiming      = SiS310_PALTiming;
-   SiS_Pr->SiS_HiTVSt1Timing  = SiS310_HiTVSt1Timing;
-   SiS_Pr->SiS_HiTVSt2Timing  = SiS310_HiTVSt2Timing;
-   SiS_Pr->SiS_HiTVTextTiming = SiS310_HiTVTextTiming;
-   SiS_Pr->SiS_HiTVExtTiming  = SiS310_HiTVExtTiming;
-   SiS_Pr->SiS_HiTVGroup3Data = SiS310_HiTVGroup3Data;
-   SiS_Pr->SiS_HiTVGroup3Simu = SiS310_HiTVGroup3Simu;
-   SiS_Pr->SiS_HiTVGroup3Text = SiS310_HiTVGroup3Text;
 
-   SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
    SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS;
 
-   SiS_Pr->SiS_LVDS800x600Data_1   = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_1;
-   SiS_Pr->SiS_LVDS800x600Data_2   = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_2;
-   SiS_Pr->SiS_LVDS1024x768Data_1  = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_1;
-   SiS_Pr->SiS_LVDS1024x768Data_2  = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_2;
-   SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_1;
-   SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_2;
-   SiS_Pr->SiS_LVDS1280x960Data_1  = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_1;
-   SiS_Pr->SiS_LVDS1280x960Data_2  = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_2;
-   SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_1;
-   SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_2;
-   SiS_Pr->SiS_LVDS1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1600x1200Data_1;
-   SiS_Pr->SiS_LVDS1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1600x1200Data_2;
-   SiS_Pr->SiS_LVDS1280x768Data_1  = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_1;
-   SiS_Pr->SiS_LVDS1280x768Data_2  = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_2;
-   SiS_Pr->SiS_LVDS1024x600Data_1  = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_1;
-   SiS_Pr->SiS_LVDS1024x600Data_2  = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_2;
-   SiS_Pr->SiS_LVDS1152x768Data_1  = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_1;
-   SiS_Pr->SiS_LVDS1152x768Data_2  = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_2;
-   SiS_Pr->SiS_LVDSXXXxXXXData_1   = (SiS_LVDSDataStruct *)SiS310_LVDSXXXxXXXData_1;
-   SiS_Pr->SiS_LVDS320x480Data_1   = (SiS_LVDSDataStruct *)SiS310_LVDS320x480Data_1;
-   SiS_Pr->SiS_LVDS640x480Data_1   = (SiS_LVDSDataStruct *)SiS310_LVDS640x480Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_1  = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_2  = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_2;
-   SiS_Pr->SiS_LCDA1600x1200Data_1  = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_1;
-   SiS_Pr->SiS_LCDA1600x1200Data_2  = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_2;
-   SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVONTSCData;
    SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData;
    SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData;
    SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData;
@@ -513,6 +529,7 @@
    SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData;
    SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData;
    SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData;
+
    SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1;
    SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1;
    SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1;
@@ -545,19 +562,7 @@
    SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2;
    SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2;
    SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2;
-   SiS_Pr->SiS_PanelTypeNS_1 = (SiS_LVDSDesStruct *)SiS310_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = (SiS_LVDSDesStruct *)SiS310_PanelTypeNS_2;
-
-   SiS_Pr->LVDS1024x768Des_1  = (SiS_LVDSDesStruct *)SiS310_PanelType1076_1;
-   SiS_Pr->LVDS1280x1024Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_1;
-   SiS_Pr->LVDS1400x1050Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_1 ;
-   SiS_Pr->LVDS1600x1200Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_1 ;
-   SiS_Pr->LVDS1024x768Des_2  = (SiS_LVDSDesStruct *)SiS310_PanelType1076_2;
-   SiS_Pr->LVDS1280x1024Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_2;
-   SiS_Pr->LVDS1400x1050Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_2;
-   SiS_Pr->LVDS1600x1200Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_2 ;
 
-   /* TW: New from 650/301LV BIOS */
    SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1;
    SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1;
    SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1;
@@ -571,51 +576,32 @@
    SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3;
    SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3;
 
-   SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = (SiS_LVDSDesStruct *)SiS310_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = (SiS_LVDSDesStruct *)SiS310_CHTVOPALDesData;
-
    SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1;
    SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1;
    SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1;
    SiS_Pr->SiS_LVDSCRT11400x1050_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1;
-   SiS_Pr->SiS_LVDSCRT11280x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1;
-   SiS_Pr->SiS_LVDSCRT11024x600_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1;
-   SiS_Pr->SiS_LVDSCRT11152x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1;
    SiS_Pr->SiS_LVDSCRT11600x1200_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1;
    SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H;
    SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H;
    SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H;
    SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1_H;
    SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H;
    SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2;
    SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2;
    SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2;
    SiS_Pr->SiS_LVDSCRT11400x1050_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2;
-   SiS_Pr->SiS_LVDSCRT11280x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2;
-   SiS_Pr->SiS_LVDSCRT11024x600_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2;
-   SiS_Pr->SiS_LVDSCRT11152x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2;
    SiS_Pr->SiS_LVDSCRT11600x1200_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2;
    SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H;
    SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H;
    SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H;
    SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2_H;
    SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1_H;
-   SiS_Pr->SiS_LVDSCRT1320x480_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1320x480_1;
-   SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1SOPAL;
+   SiS_Pr->SiS_CHTVCRT1UNTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1SOPAL;
+
    SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC;
    SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC;
    SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL;
@@ -625,6 +611,7 @@
    SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN;
    SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN;
    SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_SOPAL;
+
    SiS_Pr->SiS_LCDACRT1800x600_1     = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1;
    SiS_Pr->SiS_LCDACRT11024x768_1    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1;
    SiS_Pr->SiS_LCDACRT11280x1024_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1;
@@ -645,6 +632,7 @@
    SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H;
    SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H;
    SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H;
+
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
    SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
@@ -667,9 +655,13 @@
    SiS_Pr->SiS_Panel1152x864  = Panel_1152x864;
    SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
    SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
+   SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2;
+   SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3;
    SiS_Pr->SiS_PanelMax       = Panel_320x480;    /* TW: highest value */
    SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* TW: lowest value LVDS/LCDA */
    SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* TW: lowest value 301 */
+   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
+   SiS_Pr->SiS_PanelBarco1366 = 255;
 }
 #endif
 
@@ -732,7 +724,8 @@
       (HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330))
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660))
      InitTo310Pointer(SiS_Pr, HwDeviceExtension);
 #endif
 
@@ -901,7 +894,8 @@
       (HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330)) {
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660)) {
    	for(i=0x12; i<=0x1B; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0);
    	for(i=0x79; i<=0x7C; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0);
    }
@@ -958,14 +952,15 @@
    if((HwDeviceExtension->jChipType == SIS_315H)   ||
       (HwDeviceExtension->jChipType == SIS_315)    ||
       (HwDeviceExtension->jChipType == SIS_315PRO) ||
-      (HwDeviceExtension->jChipType == SIS_330) ) {
+      (HwDeviceExtension->jChipType == SIS_330)) {
       	if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) {
           	temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A) & 0x03;
         }
    }
    if((HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_650)) {
+      (HwDeviceExtension->jChipType == SIS_650) ||
+      (HwDeviceExtension->jChipType == SIS_660)) {
         if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) {
           	temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07;
         }
@@ -982,7 +977,7 @@
    if((HwDeviceExtension->jChipType != SIS_540) &&
       (HwDeviceExtension->jChipType != SIS_630) &&
       (HwDeviceExtension->jChipType != SIS_730)){
-     	for(i=0x15;i<0x1C;i++) {
+     	for(i=0x15; i<0x1C; i++) {
        	    SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SiS_Pr->SiS_SR15[i-0x15][SiS_Pr->SiS_RAMType]);
      	}
    }
@@ -1028,7 +1023,8 @@
       (HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330))
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660))
      	SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2E,0x08);    /* use VB */
 #endif
 
@@ -1185,7 +1181,8 @@
 #ifdef SIS315H
   if((HwDeviceExtension->jChipType == SIS_650) ||
      (HwDeviceExtension->jChipType == SIS_740) ||
-     (HwDeviceExtension->jChipType == SIS_330)) {
+     (HwDeviceExtension->jChipType == SIS_330) ||
+     (HwDeviceExtension->jChipType == SIS_660)) {
 #if 0 /* TW: This is not required */
         /* TW: Read POWER_ON_TRAP and copy to CR37 */
     	temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A);
@@ -1304,7 +1301,7 @@
 #endif
 /* ===============  SiS 300 dram sizing end    =============== */
 
-/* ============  SiS 310/325 dram sizing begin  ============== */
+/* ============  SiS 315 dram sizing begin  ============== */
 #ifdef SIS315H
 
 /* TW: Moved Get310DRAMType further down */
@@ -1898,8 +1895,7 @@
    if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
      data = *SiS_Pr->pSiS_SoftSetting & 0x03;
    } else {
-     if((HwDeviceExtension->jChipType > SIS_315PRO) &&
-        (HwDeviceExtension->jChipType < SIS_330)) {
+     if(IS_SIS550650740660) {
         data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07;
      } else {	/* TW: 315, 330 */
         data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
@@ -1939,13 +1935,17 @@
    SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
    SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
    SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
-   SiS_Pr->SiS_P3da = BaseAddr + 0x2A;
-   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;   /* Digital video interface registers (LCD) */
-   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;   /* 301 TV Encoder registers */
-   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;   /* 301 Macrovision registers */
-   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;   /* 301 VGA2 (and LCD) registers */
-   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14+2; /* 301 palette address port registers */
-   SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;                /* DDC Port ( = P3C4, SR11/0A) */
+   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;     /* Digital video interface registers (LCD) */
+   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;     /* 301 TV Encoder registers */
+   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;     /* 301 Macrovision registers */
+   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;     /* 301 VGA2 (and LCD) registers */
+   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */
+   SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;                  /* DDC Port ( = P3C4, SR11/0A) */
+   SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
+   SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
 }
 
 void
@@ -1970,7 +1970,8 @@
       (HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330)) {
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660)) {
       /* TW: This seems to be done the same way on these chipsets */
       SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1);
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A);
@@ -1992,10 +1993,14 @@
 
    SiS_Pr->SiS_ChrontelInit = 0;
 
-   if((ModeNo == 0x5a) || (ModeNo == 0x5b)) {
-   	SiS_Pr->SiS_IF_DEF_DSTN = 1;   /* for 550 dstn */
-   	SiS_Pr->SiS_IF_DEF_FSTN = 1;   /* for fstn */
+#if 0
+   if(HwDeviceExtension->jChipType >= SIS_315H) {
+      if((ModeNo == 0x5a) || (ModeNo == 0x5b)) {
+   	 SiS_Pr->SiS_IF_DEF_DSTN = 1;   /* for 550 dstn */
+   	 SiS_Pr->SiS_IF_DEF_FSTN = 1;   /* for fstn */
+      }
    }
+#endif
 
 #ifdef SIS300
    if((HwDeviceExtension->jChipType == SIS_540) ||
@@ -2020,11 +2025,14 @@
    if((HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330))
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660))
     {
-        /* TW: CR37 is different on 310/325 series */
+        /* TW: CR37 is different on 315 series */
+#if 0
         if(SiS_Pr->SiS_IF_DEF_FSTN)                       /* fstn: set CR37=0x04 */
              SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x04);      /* (fake LVDS bridge) */
+#endif
 
 	temp=SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
@@ -2049,7 +2057,8 @@
       (HwDeviceExtension->jChipType == SIS_550) ||
       (HwDeviceExtension->jChipType == SIS_650) ||
       (HwDeviceExtension->jChipType == SIS_740) ||
-      (HwDeviceExtension->jChipType == SIS_330))
+      (HwDeviceExtension->jChipType == SIS_330) ||
+      (HwDeviceExtension->jChipType == SIS_660))
      InitTo310Pointer(SiS_Pr, HwDeviceExtension);
 #endif
 
@@ -2078,14 +2087,21 @@
 	      SiS_Pr->SiS_UseROM = TRUE;
 	 else SiS_Pr->SiS_UseROM = FALSE;
      } else if(HwDeviceExtension->jChipType < SIS_315H) {
+#if 0
         /* TW: Rest of 300 series: We don't use the ROM image if
 	 *     the BIOS version < 2.0.0 as such old BIOSes don't
 	 *     have the needed data at the expected locations.
 	 */
         if(ROMAddr[0x06] < '2')  SiS_Pr->SiS_UseROM = FALSE;
 	else                     SiS_Pr->SiS_UseROM = TRUE;
+#else
+	/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
+	 * the others do as well
+	 */
+	SiS_Pr->SiS_UseROM = TRUE;
+#endif
      } else {
-        /* TW: 310/325/330 series stick to the standard */
+        /* TW: 315/330 series stick to the standard */
 	SiS_Pr->SiS_UseROM = TRUE;
      }
    } else SiS_Pr->SiS_UseROM = FALSE;
@@ -2109,24 +2125,27 @@
    SiS_Pr->UseCustomMode = FALSE;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
-   
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n", 
-	 	SiS_Pr->CHDisplay, SiS_Pr->CVDisplay);
-		
+
+         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
+	 	SiS_Pr->CHDisplay,
+		(mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
+		   (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
+		      SiS_Pr->CVDisplay)));
+
 	 return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE));
-   
+
    }
-   
-   ModeNo = SiS_CalcModeIndex(pScrn, mode);
+
+   ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->HaveCustomModes);
    if(!ModeNo) return FALSE;
 
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting mode 0x%x\n", ModeNo);
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
 
    return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE));   
 }
 
 #ifdef SISDUALHEAD
-/* TW: Set CRT1 mode (used for dual head) */
+/* TW: Set CRT1 mode (used for dual head and MergedFB) */
 BOOLEAN
 SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
@@ -2139,31 +2158,37 @@
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
    unsigned char backupreg=0;
    BOOLEAN backupcustom;
-
    UShort  ModeNo=0;
    
    SiS_Pr->UseCustomMode = FALSE;
-   
+
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
-   
+
+         USHORT temptemp = SiS_Pr->CVDisplay;
+
+         if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
+         else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
+
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-	 	"Setting custom mode %dx%d in CRT1\n", 
-	 	SiS_Pr->CHDisplay, SiS_Pr->CVDisplay);
+	 	"Setting custom mode %dx%d on CRT1\n",
+	 	SiS_Pr->CHDisplay, temptemp);
 	 ModeNo = 0xfe;
-	 
+
    } else {
 
-         ModeNo = SiS_CalcModeIndex(pScrn, mode);
+         ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->HaveCustomModes);
          if(!ModeNo) return FALSE;
 
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-	 	"Setting mode 0x%x on CRT1\n", ModeNo);
+	 	"Setting standard mode 0x%x on CRT1\n", ModeNo);
    }
 
    SiSInitPtr(SiS_Pr, HwDeviceExtension);
 
    SiSRegInit(SiS_Pr, BaseAddr);
 
+   SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
+
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
 
    SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
@@ -2172,7 +2197,7 @@
 
    SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr);
 
-   /* TW: We don't clear the buffer under X */
+   /* We don't clear the buffer under X */
    SiS_Pr->SiS_flag_clearbuffer = 0;
 
    /* 1.Openkey */
@@ -2180,8 +2205,8 @@
 
    SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
 
+   /* 2.Get ModeID Table  */
    if(!SiS_Pr->UseCustomMode) {
-      /* 2.Get ModeID Table  */
       temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
       if(temp == 0)  return(0);
    } else {
@@ -2206,57 +2231,65 @@
    SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
 
    if(HwDeviceExtension->jChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-         if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+      if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
             if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
+         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+            SiS_Pr->SiS_SetFlag |= SetDOSMode;
          }
       }
 
-      /* TW: New from 650/LV 1.10.6x */
       if(IS_SIS650) {
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	  }
+         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	    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);
+	 }
       }
    }
 
-   /* TW: Set mode on CRT1 */
+   /* Set mode on CRT1 */
    SiS_SetCRT1Group(SiS_Pr, ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr);
 
+   /* SetPitch: Adapt to virtual size & position */
+   SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr);
+
    if(pSiS->DualHeadMode) {
       pSiSEnt->CRT1ModeNo = ModeNo;
       pSiSEnt->CRT1DMode = mode;
    }
 
-   /* TW: SetPitch: Adapt to virtual size & position */
-   SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr);
+   if(SiS_Pr->UseCustomMode) {
+      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
+      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
+   } else {
+      SiS_Pr->CRT1UsesCustomMode = FALSE;
+   }
 
    /* We have to reset CRT2 if changing mode on CRT1 */
    if(pSiS->DualHeadMode) {
       if(pSiSEnt->CRT2ModeNo != -1) {
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-				"(Re-)Setting mode 0x%x on CRT2\n",
-				pSiSEnt->CRT2ModeNo);
+				"(Re-)Setting mode for CRT2\n");
 	 backupcustom = SiS_Pr->UseCustomMode;
-	 if(SiS_Pr->UseCustomMode) {
-	    SiS_Pr->CRT1UsesCustomMode = TRUE;
-	 } else {
-	    SiS_Pr->CRT1UsesCustomMode = FALSE;
-	 }
 	 SiSBIOSSetModeCRT2(SiS_Pr, HwDeviceExtension, pSiSEnt->pScrn_1,
-				pSiSEnt->CRT2DMode);
+			    pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
 	 SiS_Pr->UseCustomMode = backupcustom;
-	 SiS_Pr->CRT1UsesCustomMode = FALSE;
       }
    }
-   
+
+   /* Warning: From here, the custom mode entries in SiS_Pr are
+    * possibly overwritten
+    */
+
    SiS_HandleCRT1(SiS_Pr);
 
+   SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
+
    SiS_DisplayOn(SiS_Pr);
    SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
 
-   /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630/301B 2.06.50 */
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwDeviceExtension->jChipType >= SIS_315H) {
 	 SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,backupreg);
@@ -2275,7 +2308,7 @@
 /* TW: Set CRT2 mode (used for dual head) */
 BOOLEAN
 SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn,
-               DisplayModePtr mode)
+               DisplayModePtr mode, BOOLEAN IsCustom)
 {
    ULONG   temp;
    USHORT  ModeIdIndex;
@@ -2285,33 +2318,39 @@
    SISPtr  pSiS     = SISPTR(pScrn);
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
    unsigned char tempr1, tempr2, backupreg=0;
-   
+
    SiS_Pr->UseCustomMode = FALSE;
-   
-   ModeNo = SiS_CalcModeIndex(pScrn, mode);
-   if(!ModeNo) return FALSE;
 
-   SiSInitPtr(SiS_Pr, HwDeviceExtension);
+   /* Remember: Custom modes for CRT2 are ONLY supported
+    * 		-) on 315/330 series,
+    *           -) on the 301 and 30xB, and
+    *           -) if CRT2 is LCD or VGA
+    */
 
-   SiSRegInit(SiS_Pr, BaseAddr);
+   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
-   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+	 ModeNo = 0xfe;
 
-   SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
+   } else {
 
-   SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo);
+         BOOLEAN havecustommodes = pSiS->HaveCustomModes;
 
-   SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr);
+#ifdef SISMERGED
+	 if(pSiS->MergedFB) havecustommodes = pSiS->HaveCustomModes2;
+#endif
 
-   /* TW: We don't clear the buffer under X */
-   SiS_Pr->SiS_flag_clearbuffer=0;
+         ModeNo = SiS_CalcModeIndex(pScrn, mode, havecustommodes);
+         if(!ModeNo) return FALSE;
+
+   }
 
-   /* TW: Save ModeNo so we can set it from within SetMode for CRT1 */
+   /* Save mode info so we can set it from within SetMode for CRT1 */
    if(pSiS->DualHeadMode) {
       pSiSEnt->CRT2ModeNo = ModeNo;
       pSiSEnt->CRT2DMode = mode;
+      pSiSEnt->CRT2IsCustom = IsCustom;
 
-      /* TW: We can't set CRT2 mode before CRT1 mode is set */
+      /* We can't set CRT2 mode before CRT1 mode is set */
       if(pSiSEnt->CRT1ModeNo == -1) {
     	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
 		"Setting CRT2 mode delayed until after setting CRT1 mode\n");
@@ -2319,8 +2358,40 @@
       }
    }
 
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-   		"Setting mode 0x%x on CRT2\n", ModeNo);
+   SiSInitPtr(SiS_Pr, HwDeviceExtension);
+
+   SiSRegInit(SiS_Pr, BaseAddr);
+
+   SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
+
+   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+
+   SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
+
+   SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo);
+
+   SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr);
+
+   /* We don't clear the buffer under X */
+   SiS_Pr->SiS_flag_clearbuffer=0;
+
+   if(SiS_Pr->UseCustomMode) {
+
+      USHORT temptemp = SiS_Pr->CVDisplay;
+
+      if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
+      else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
+
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+	  "Setting custom mode %dx%d on CRT2\n",
+	  SiS_Pr->CHDisplay, temptemp);
+
+   } else {
+
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+   	  "Setting standard mode 0x%x on CRT2\n", ModeNo);
+
+   }
 
    /* 1.Openkey */
    SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86);
@@ -2328,10 +2399,14 @@
    SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
 
    /* 2.Get ModeID */
-   temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
-   if(temp == 0)  return(0);
+   if(!SiS_Pr->UseCustomMode) {
+      temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
+      if(temp == 0)  return(0);
+   } else {
+      ModeIdIndex = 0;
+   }
 
-   /* TW: Determine VBType (301,301B,301LV,302B,302LV) */
+   /* Determine VBType (301,301B,301LV,302B,302LV) */
    SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension);
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
@@ -2354,15 +2429,22 @@
       }
    }
 
-   /* TW: Get VB information (connectors, connected devices) */
-   SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
+   /* Get VB information (connectors, connected devices) */
+   if(!SiS_Pr->UseCustomMode) {
+      SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
+   } else {
+      /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
+      SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,0);
+   }
    SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension);
    SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
 
    if(HwDeviceExtension->jChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-         if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+      if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
             if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
+         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+            SiS_Pr->SiS_SetFlag |= SetDOSMode;
          }
       }
    }
@@ -2375,17 +2457,19 @@
      case VB_CHIP_302:
      case VB_CHIP_302B:
      case VB_CHIP_302LV:
-        SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+        SiS_SetCRT2Group(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
         break;
      case VB_CHIP_UNKNOWN:
-        if (SiS_Pr->SiS_IF_DEF_LVDS     == 1 ||
-	    SiS_Pr->SiS_IF_DEF_CH70xx   != 0 ||
-	    SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
-             	SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+        if(SiS_Pr->SiS_IF_DEF_LVDS     == 1 ||
+	   SiS_Pr->SiS_IF_DEF_CH70xx   != 0 ||
+	   SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
+           SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
   	}
         break;
    }
 
+   SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
+
    SiS_DisplayOn(SiS_Pr);
    SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
 
@@ -2397,7 +2481,6 @@
       }
    }
 
-   /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630 2.06.50 */
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwDeviceExtension->jChipType >= SIS_315H) {
 	 if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
@@ -2423,7 +2506,7 @@
       }
    }
 
-   /* TW: SetPitch: Adapt to virtual size & position */
+   /* SetPitch: Adapt to virtual size & position */
    SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr);
 
    return TRUE;
@@ -2459,6 +2542,8 @@
 
    SiSRegInit(SiS_Pr, BaseAddr);
 
+   SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
+
 #ifdef LINUX_XF86
    if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
    else
@@ -2469,7 +2554,7 @@
 #ifdef TWDEBUG
    xf86DrvMsg(0, X_INFO, "VGAInfo 0x%02x\n", SiS_Pr->SiS_VGAINFO);
 #endif
-#endif	 	 
+#endif
 
    SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
 
@@ -2483,7 +2568,7 @@
    }      
 
 #ifdef LINUX_XF86
-   /* TW: We never clear the buffer in X */
+   /* We never clear the buffer in X */
    ModeNo |= 0x8000;
 #endif
 
@@ -2512,10 +2597,10 @@
       
    }
     
-   /* TW: Determine VBType (301,301B,301LV,302B,302LV) */
+   /* Determine VBType (301,301B,301LV,302B,302LV) */
    SiS_GetVBType(SiS_Pr,BaseAddr,HwDeviceExtension);
 
-   /* TW: Init/restore some VB registers */
+   /* Init/restore some VB registers */
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
        if(HwDeviceExtension->jChipType >= SIS_315H) {
          SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr);
@@ -2536,8 +2621,12 @@
        }
    }
    
-   /* TW: Get VB information (connectors, connected devices) */
-   SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
+   /* Get VB information (connectors, connected devices) */
+   if(SiS_Pr->UseCustomMode) {
+      SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,0);
+   } else {
+      SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
+   }
    SiS_SetHiVision(SiS_Pr,BaseAddr,HwDeviceExtension);
    SiS_GetLCDResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
 
@@ -2546,22 +2635,32 @@
    if(!temp) return(0);
 
    if(HwDeviceExtension->jChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-         if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+      if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
+         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
             if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
+         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+            SiS_Pr->SiS_SetFlag |= SetDOSMode;
          }
       }
 
-      /* TW: New from 650/LV 1.10.6x; not in any BIOS for other chipsets */
       if(IS_SIS650) {
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	  }
+         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	    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);
+	 }
       }
    }
 
-   /* TW: Set mode on CRT1 */
+   if(SiS_Pr->UseCustomMode) {
+      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
+      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
+   } else {
+      SiS_Pr->CRT1UsesCustomMode = FALSE;
+   }
+
+   /* Set mode on CRT1 */
    if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
    	SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr);
    } else {
@@ -2570,7 +2669,7 @@
      }
    }
 
-   /* TW: Set mode on CRT2 */
+   /* Set mode on CRT2 */
    if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA)) {
      switch (HwDeviceExtension->ujVBChipID) {
      case VB_CHIP_301:
@@ -2579,18 +2678,20 @@
      case VB_CHIP_302:
      case VB_CHIP_302B:
      case VB_CHIP_302LV:
-        SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+        SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
         break;
      case VB_CHIP_UNKNOWN:
 	if(SiS_Pr->SiS_IF_DEF_LVDS     == 1 ||
 	   SiS_Pr->SiS_IF_DEF_CH70xx   != 0 ||
 	   SiS_Pr->SiS_IF_DEF_TRUMPION != 0)
-             	SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+           SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
         break;
      }
    }
    
    SiS_HandleCRT1(SiS_Pr);
+
+   SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
    
    SiS_DisplayOn(SiS_Pr);
    SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
@@ -2603,7 +2704,6 @@
       }
    }
 
-   /* TW: New from 650/LV 1.10.6x and 1.10.7w */
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwDeviceExtension->jChipType >= SIS_315H) {
 	 if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
@@ -2638,7 +2738,7 @@
 
 #ifdef LINUX_XF86
    if(pScrn) {
-      /* TW: SetPitch: Adapt to virtual size & position */
+      /* SetPitch: Adapt to virtual size & position */
       if((ModeNo > 0x13) && (dosetpitch)) {
          SiS_SetPitch(SiS_Pr, pScrn, BaseAddr);
       }
@@ -2648,7 +2748,7 @@
    }
 #endif
 
-#ifndef LINUX_XF86  /* TW: We never lock registers in XF86 */
+#ifndef LINUX_XF86  /* We never lock registers in XF86 */
    if(KeepLockReg == 0xA1) SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86);
    else SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x00);
 #endif
@@ -2657,10 +2757,15 @@
 }
 
 void
-SiS_SetEnableDstn(SiS_Private *SiS_Pr)	/* TW: Called from sis_main.c */
+SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable)
+{
+   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
+}
+
+void
+SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable)
 {
-   /* For 550 dstn */
-   SiS_Pr->SiS_IF_DEF_DSTN = 1;
+   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
 }
 
 void
@@ -2674,13 +2779,73 @@
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf);
 
 #if 0
-  if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01))
-     SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
+  if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+     if((SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+        (SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
+     }
   }
 #endif
 }
 
 void
+SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+   unsigned char cr5f, temp1, temp2;
+
+   /* You should use the macros, not these flags directly */
+
+   SiS_Pr->SiS_SysFlags = 0;
+   if(HwDeviceExtension->jChipType == SIS_650) {
+      cr5f = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
+      temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
+      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
+      temp2 = SiS_GetReg1(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_GetReg1(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;
+	 }
+      }
+   }
+}
+
+void
+SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+   if((IS_SIS651) || (IS_SISM650)) {
+      SiS_SetReg1(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
+      SiS_SetReg1(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
+      SiS_SetReg1(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
+      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
+      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
+   }
+   /* !!! This does not support modes < 0x13 !!! */
+}
+
+void
 SiS_SetCRT1Group(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension,
                  USHORT ModeNo,USHORT ModeIdIndex,USHORT BaseAddr)
 {
@@ -2694,6 +2859,9 @@
     }
   }
 
+  /* 550, 651 */
+  SiS_WhatTheHellIsThis(SiS_Pr,HwDeviceExtension,BaseAddr);
+
   SiS_SetSeqRegs(SiS_Pr,ROMAddr,StandTableIndex);
   SiS_SetMiscRegs(SiS_Pr,ROMAddr,StandTableIndex);
   SiS_SetCRTCRegs(SiS_Pr,ROMAddr,HwDeviceExtension,StandTableIndex);
@@ -2770,15 +2938,20 @@
 SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr)
 {
    SISPtr pSiS = SISPTR(pScrn);
+   BOOLEAN isslavemode = FALSE;
 
-   /* TW: We need to set pitch for CRT1 if bridge is in SlaveMode, too */
-   if( (pSiS->VBFlags & DISPTYPE_DISP1) ||
-       ( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
-         ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
-           ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) ) {
+   if( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
+       ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
+         ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
+      isslavemode = TRUE;
+   }
+
+   /* We need to set pitch for CRT1 if bridge is in slave mode, too */
+   if( (pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode) ) {
    	SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr);
    }
-   if (pSiS->VBFlags & DISPTYPE_DISP2) {
+   /* We must not set the pitch for CRT2 if bridge is in slave mode */
+   if( (pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode) ) {
    	SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr);
    }
 }
@@ -2801,7 +2974,7 @@
     SISPtr pSiS = SISPTR(pScrn);
     ULong  HDisplay,temp;
 
-    HDisplay = pSiS->scrnPitch / 8;
+    HDisplay = pSiS->scrnPitch2 / 8;
 
     /* Unlock CRT2 */
     if (pSiS->VGAEngine == SIS_315_VGA)
@@ -2891,7 +3064,6 @@
    return TRUE;
 }
 
-/* For SiS 300 oem util: Search VBModeID */
 BOOLEAN
 SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo)
 {
@@ -2957,6 +3129,81 @@
    return index;
 }
 
+static void
+SiS_WhatIsThis1a(SiS_Private *SiS_Pr, USHORT somevalue)
+{
+   USHORT temp, tempbl, tempbh;
+
+   tempbl = tempbh = somevalue;
+   temp = SiS_GetReg2(SiS_Pr->SiS_P3cb);
+   temp &= 0xf0;
+   tempbl >>= 4;
+   temp |= tempbl;
+   SiS_SetReg3(SiS_Pr->SiS_P3cb, temp);
+   temp = SiS_GetReg2(SiS_Pr->SiS_P3cd);
+   temp &= 0xf0;
+   tempbh &= 0x0f;
+   temp |= tempbh;
+   SiS_SetReg3(SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_WhatIsThis1b(SiS_Private *SiS_Pr, USHORT somevalue)
+{
+   USHORT temp, tempbl, tempbh;
+
+   tempbl = tempbh = somevalue;
+   temp = SiS_GetReg2(SiS_Pr->SiS_P3cb);
+   temp &= 0x0f;
+   tempbl &= 0xf0;
+   temp |= tempbl;
+   SiS_SetReg3(SiS_Pr->SiS_P3cb, temp);
+   temp = SiS_GetReg2(SiS_Pr->SiS_P3cd);
+   temp &= 0x0f;
+   tempbh <<= 4;
+   temp |= tempbh;
+   SiS_SetReg3(SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_WhatIsThis2b(SiS_Private *SiS_Pr, USHORT somevalue)
+{
+   SiS_WhatIsThis1a(SiS_Pr, somevalue);
+   SiS_WhatIsThis1b(SiS_Pr, somevalue);
+}
+
+static void
+SiS_WhatIsThis1(SiS_Private *SiS_Pr)
+{
+   SiS_WhatIsThis2b(SiS_Pr, 0);
+}
+
+static void
+SiS_WhatIsThis2a(SiS_Private *SiS_Pr, USHORT somevalue)
+{
+   USHORT temp = somevalue >> 8;
+
+   temp &= 0x07;
+   temp |= (temp << 4);
+   SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1d,temp);
+   SiS_WhatIsThis2b(SiS_Pr, somevalue);
+}
+
+static void
+SiS_WhatIsThis2(SiS_Private *SiS_Pr)
+{
+   SiS_WhatIsThis2a(SiS_Pr, 0);
+}
+
+void
+SiS_WhatTheHellIsThis(SiS_Private *SiS_Pr,PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
+{
+   if(IS_SIS65x) {
+      SiS_WhatIsThis1(SiS_Pr);
+      SiS_WhatIsThis2(SiS_Pr);
+   }
+}
+
 void
 SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex)
 {
@@ -3038,7 +3285,7 @@
       (HwDeviceExtension->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-        SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE);
+         SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE);
       }
     }
   }
@@ -3076,7 +3323,7 @@
       }
       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
          if(HwDeviceExtension->jChipType >= SIS_315H) {
-	    if(IS_SIS650740 || IS_SIS550) {  
+	    if(IS_SIS550650740660) {
 	       /* 315, 330 don't do this */
 	       if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { 
 	          if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
@@ -3159,7 +3406,7 @@
   USHORT tempah,i,modeflag,j;
 #ifdef SIS315H
   USHORT temp;
-  USHORT ResInfo,DisplayType;
+  USHORT ResIndex,DisplayType;
   const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
 #endif
 
@@ -3182,7 +3429,7 @@
      /* LCDA */
 
      temp = SiS_GetLCDACRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
-                       RefreshRateTableIndex,&ResInfo,&DisplayType);
+                       RefreshRateTableIndex,&ResIndex,&DisplayType);
 
      switch(DisplayType) {
       case Panel_800x600       : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1;      break;
@@ -3208,30 +3455,30 @@
       default:                   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
      }
 
-     tempah = (LCDACRT1Ptr+ResInfo)->CR[0];
+     tempah = (LCDACRT1Ptr+ResIndex)->CR[0];
      SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah);
      for(i=0x01,j=1;i<=0x07;i++,j++){
-       tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
+       tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
        SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
      }
      for(i=0x10,j=8;i<=0x12;i++,j++){
-       tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
+       tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
        SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
      }
      for(i=0x15,j=11;i<=0x16;i++,j++){
-       tempah =(LCDACRT1Ptr+ResInfo)->CR[j];
+       tempah =(LCDACRT1Ptr+ResIndex)->CR[j];
        SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
      }
      for(i=0x0A,j=13;i<=0x0C;i++,j++){
-       tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
+       tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
        SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah);
      }
 
-     tempah = (LCDACRT1Ptr+ResInfo)->CR[16];
+     tempah = (LCDACRT1Ptr+ResIndex)->CR[16];
      tempah &= 0x0E0;
      SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah);
 
-     tempah = (LCDACRT1Ptr+ResInfo)->CR[16];
+     tempah = (LCDACRT1Ptr+ResIndex)->CR[16];
      tempah &= 0x01;
      tempah <<= 5;
      if(modeflag & DoubleScanMode)  tempah |= 0x080;
@@ -3312,7 +3559,7 @@
 
 BOOLEAN
 SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
-		   USHORT RefreshRateTableIndex,USHORT *ResInfo,
+		   USHORT RefreshRateTableIndex,USHORT *ResIndex,
 		   USHORT *DisplayType)
  {
   USHORT tempbx=0,modeflag=0;
@@ -3331,7 +3578,7 @@
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 32;
   if(modeflag & HalfDCLK)                 tempbx += 16;
 
-  *ResInfo = CRT2CRTC & 0x3F;
+  *ResIndex = CRT2CRTC & 0x3F;
   *DisplayType = tempbx;
 
   return 1;
@@ -3501,11 +3748,11 @@
 
   data2 = 0;
   if(ModeNo > 0x13) {
-    if(SiS_Pr->SiS_ModeType > 0x02) {
-       data2 |= 0x02;
-       data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2;
-       data2 |= data3;
-    }
+     if(SiS_Pr->SiS_ModeType > 0x02) {
+        data2 |= 0x02;
+        data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2;
+        data2 |= data3;
+     }
   }
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n", 
@@ -3528,7 +3775,8 @@
   if(HwDeviceExtension->jChipType != SIS_300) {
      data = 0x0000;
      if(infoflag & InterlaceMode) {
-        if(xres == 1024) data = 0x0035;
+        if(xres <= 800)  data = 0x0020;
+        else if(xres <= 1024) data = 0x0035;
         else data = 0x0048;
      }
      data2 = data & 0x00FF;
@@ -3539,17 +3787,6 @@
 
   if(modeflag & HalfDCLK) {
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
-     /* @@@@ TEST |||| */
-#if 0
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0x7F);
-     if(xres < 512) {
-	if(modeflag & DoubleScanMode) {
-           SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x80);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xF7);
-        }
-     }
-#endif     
-     /* TEST END */
   }
 
   if(HwDeviceExtension->jChipType == SIS_300) {
@@ -3571,6 +3808,7 @@
      } else {
         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7);
      }
+     /* 651 BIOS does something for mode 0x12 here */
   }
 
   if(HwDeviceExtension->jChipType != SIS_300) {
@@ -3701,7 +3939,7 @@
     if(VCLK >= 150) data2 |= 0x08;       	/* VCLK > 150 */
     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2);
 
-  } else { 						/* 310/325 series */
+  } else { 						/* 315 series */
 
     data = 0;
     if(VCLK >= 166) data |= 0x0c;         	/* TW: Was 200; is 166 in 650, 315 and 330 BIOSes */
@@ -3710,12 +3948,6 @@
     if(VCLK >= 166) {				/* TW: Was 200, is 166 in 650, 315 and 330 BIOSes */
        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
     }
-#if 0 /* Not done in 315 and 650/301LV/LVDS BIOSes: */
-    data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F);	  	/* DAC pedestal */
-    data &= 0xE7;
-    if(VCLK<200) data |= 0x10;
-    SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,data);	  	/* DAC pedestal */
-#endif
   }
 
   data2 = 0x03;
@@ -3940,7 +4172,8 @@
 
   } else if((HwDeviceExtension->jChipType == SIS_550) ||
             (HwDeviceExtension->jChipType == SIS_740) ||
-            (HwDeviceExtension->jChipType == SIS_650)) {
+            (HwDeviceExtension->jChipType == SIS_650) ||
+	    (HwDeviceExtension->jChipType == SIS_660)) {
 
   	counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
       	counter++;
@@ -4750,7 +4983,7 @@
           SiS_Pr->SiS_SetFlag = 0x00;
           SiS_Pr->SiS_ModeType = ModeVGA;
           SiS_Pr->SiS_VBInfo = SetCRT2ToRAMDAC |LoadDACFlag |SetInSlaveMode;
-          SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
+          SiS_SetCRT2Group(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
           for(i=0;i<20;i++) {
             SiS_LongWait(SiS_Pr);
           }
@@ -4788,7 +5021,7 @@
 #ifdef SIS315H
 	   if(HwDeviceExtension->jChipType >= SIS_315H) {
 	        OutputSelect = ROMAddr[0xf3];
-		if(HwDeviceExtension->jChipType == SIS_330) {
+		if(HwDeviceExtension->jChipType >= SIS_330) {
 		     OutputSelect = ROMAddr[0x11b];
 		}
 	   }
@@ -4836,7 +5069,7 @@
       SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,P2reg0);
       if(!(P2reg0 & 0x20)) {
         SiS_Pr->SiS_VBInfo = DisableCRT2Display;
-        SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
+        SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
       }
     }
   }
@@ -4906,111 +5139,6 @@
 }
 #endif /* LINUXBIOS */
 
-/*  ================ for TC only =================  */
-
-#ifdef TC
-
-int
-INT1AReturnCode(union REGS regs)
-{
-  if (regs.x.cflag)
-  {
-    /*printf("Error to find pci device!\n"); */
-    return 1;
-  }
-
-  switch(regs.h.ah)
-  {
-    case 0: return 0;
-            break;
-    case 0x81: printf("Function not support\n");
-               break;
-    case 0x83: printf("bad vendor id\n");
-               break;
-    case 0x86: printf("device not found\n");
-               break;
-    case 0x87: printf("bad register number\n");
-               break;
-    case 0x88: printf("set failed\n");
-               break;
-    case 0x89: printf("buffer too small");
-               break;
-  }
-  return 1;
-}
-
-unsigned
-FindPCIIOBase(unsigned index,unsigned deviceid)
-{
-  union REGS regs;
-
-  regs.h.ah = 0xb1;  /*PCI_FUNCTION_ID */
-  regs.h.al = 0x02;  /*FIND_PCI_DEVICE */
-  regs.x.cx = deviceid;
-  regs.x.dx = 0x1039;
-  regs.x.si = index;  /* find n-th device */
-
-  int86(0x1A, &regs, &regs);
-
-  if (INT1AReturnCode(regs)!=0)
-    return 0;
-
-  /* regs.h.bh *//* bus number */
-  /* regs.h.bl *//* device number */
-  regs.h.ah = 0xb1;  /*PCI_FUNCTION_ID */
-  regs.h.al = 0x09;  /*READ_CONFIG_WORD */
-  regs.x.cx = deviceid;
-  regs.x.dx = 0x1039;
-  regs.x.di = 0x18;  /* register number */
-  int86(0x1A, &regs, &regs);
-
-  if (INT1AReturnCode(regs)!=0)
-    return 0;
-  return regs.x.cx;
-}
-
-
-void
-main(int argc, char *argv[])
-{
-  SIS_HW_DEVICE_INFO  HwDeviceExtension;
-  USHORT temp;
-  USHORT ModeNo;
-
-  /*HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
-  /*HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0);*/
-
-#ifdef SIS300  
-  HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x6300)&0xFF80) + 0x30;
-  HwDeviceExtension.jChipType = SIS_630;
-#endif
-
-#ifdef SIS315H  
-//  HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x5315)&0xFF80) + 0x30;
-//  HwDeviceExtension.jChipType = SIS_550;
-  HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x325)&0xFF80) + 0x30;
-  HwDeviceExtension.jChipType = SIS_315H;
-#endif
-
-  HwDeviceExtension.ujVBChipID = VB_CHIP_301;
-  strcpy(HwDeviceExtension.szVBIOSVer,"0.84");
-  HwDeviceExtension.bSkipDramSizing = FALSE;
-  HwDeviceExtension.ulVideoMemorySize = 0;
-  if(argc==2) {
-    ModeNo=atoi(argv[1]);
-  }
-  else {
-    ModeNo=0x2e;
-    /*ModeNo=0x37; */ /* 1024x768x 4bpp */
-    /*ModeNo=0x38; *//* 1024x768x 8bpp */
-    /*ModeNo=0x4A; *//* 1024x768x 16bpp */
-    /*ModeNo=0x47;*/ /* 800x600x 16bpp */
-  }
- /* SiSInit(SiS_Pr, &HwDeviceExtension);*/
-  SiSSetMode(SiS_Pr, &HwDeviceExtension, ModeNo);
-}
-#endif /* TC END */
-
 /* ================ XFREE86 ================= */
 
 /* Helper functions */
@@ -5022,47 +5150,78 @@
    SISPtr pSiS = SISPTR(pScrn);
    int    out_n, out_dn, out_div, out_sbit, out_scale;
    int    depth = pSiS->CurrentLayout.bitsPerPixel;
+   unsigned int vclk[5];
 
-#ifdef SISMERGED
-   if(!pSiS->MergedFB)
-#endif   
-#ifdef SISDUALHEAD
-      if( ((!pSiS->DualHeadMode) && (VBFlags & DISPTYPE_DISP2)) ||
-          ((pSiS->DualHeadMode) && (!pSiS->SecondHead)) ) return 0;
-#else
-      if(VBFlags & DISPTYPE_DISP2) return 0;
-#endif   
+#define Midx         0
+#define Nidx         1
+#define VLDidx       2
+#define Pidx         3
+#define PSNidx       4
+
+   pSiS->SiS_Pr->CModeFlag = 0;
    
    pSiS->SiS_Pr->CDClock = mode->Clock;
-   
+
    pSiS->SiS_Pr->CHDisplay = mode->HDisplay;
    pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart;
    pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd;
    pSiS->SiS_Pr->CHTotal = mode->HTotal;
-   pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
-   pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
-   
+
    pSiS->SiS_Pr->CVDisplay = mode->VDisplay;
    pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart;
    pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd;
    pSiS->SiS_Pr->CVTotal = mode->VTotal;
+
+   pSiS->SiS_Pr->CFlags = mode->Flags;
+
+   if(pSiS->SiS_Pr->CFlags & V_INTERLACE) {
+         pSiS->SiS_Pr->CVDisplay >>= 1;
+	 pSiS->SiS_Pr->CVSyncStart >>= 1;
+	 pSiS->SiS_Pr->CVSyncEnd >>= 1;
+	 pSiS->SiS_Pr->CVTotal >>= 1;
+   }
+   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) {
+         /* pSiS->SiS_Pr->CDClock <<= 1; */
+	 pSiS->SiS_Pr->CVDisplay <<= 1;
+	 pSiS->SiS_Pr->CVSyncStart <<= 1;
+	 pSiS->SiS_Pr->CVSyncEnd <<= 1;
+	 pSiS->SiS_Pr->CVTotal <<= 1;
+   }
+
+   pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
+   pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
    pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1;
    pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal;
-   
-   pSiS->SiS_Pr->CFlags = mode->Flags;
 
-   SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale);
-   
+   if(SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) {
+      pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00;
+      pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f);
+      pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f;
+      pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5);
+      pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7);
+#ifdef TWDEBUG
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
+        	pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale);
+#endif
+   } else {
+      SiSCalcClock(pScrn, pSiS->SiS_Pr->CDClock, 2, vclk);
+      pSiS->SiS_Pr->CSR2B = (vclk[VLDidx] == 2) ? 0x80 : 0x00;
+      pSiS->SiS_Pr->CSR2B |= (vclk[Midx] - 1) & 0x7f;
+      pSiS->SiS_Pr->CSR2C = (vclk[Nidx] - 1) & 0x1f;
+      if(vclk[Pidx] <= 4) {
+         /* postscale 1,2,3,4 */
+         pSiS->SiS_Pr->CSR2C |= ((vclk[Pidx] - 1) & 3) << 5;
+      } else {
+         /* postscale 6,8 */
+         pSiS->SiS_Pr->CSR2C |= (((vclk[Pidx] / 2) - 1) & 3) << 5;
+	 pSiS->SiS_Pr->CSR2C |= 0x80;
+      }
 #ifdef TWDEBUG
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
-      	pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale);
-#endif	
-
-   pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00;
-   pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f);
-   pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f;
-   pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5);
-   pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7);
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n",
+        	pSiS->SiS_Pr->CDClock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]);
+#endif
+   }
+
    pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
 
    pSiS->SiS_Pr->CCRT1CRTC[0]  =  ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff;
@@ -5070,9 +5229,9 @@
    pSiS->SiS_Pr->CCRT1CRTC[2]  =  (pSiS->SiS_Pr->CHBlankStart >> 3) - 1;
    pSiS->SiS_Pr->CCRT1CRTC[3]  =  (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
    pSiS->SiS_Pr->CCRT1CRTC[4]  =  (pSiS->SiS_Pr->CHSyncStart >> 3) + 3;
-   pSiS->SiS_Pr->CCRT1CRTC[5]  =  ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | 
+   pSiS->SiS_Pr->CCRT1CRTC[5]  =  ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
        				  (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
-   
+
    pSiS->SiS_Pr->CCRT1CRTC[6]  =  (pSiS->SiS_Pr->CVTotal - 2) & 0xFF;
    pSiS->SiS_Pr->CCRT1CRTC[7]  =  (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8)
  	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
@@ -5082,50 +5241,50 @@
 	 			| (((pSiS->SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
 	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
 	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2);
-    
+
    pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* cr9 */
-    
-#if 0    
+
+#if 0
    if (mode->VScan >= 32)
 	regp->CRTC[9] |= 0x1F;
    else if (mode->VScan > 1)
 	regp->CRTC[9] |= mode->VScan - 1;
-#endif	
+#endif
 
-   pSiS->SiS_Pr->CCRT1CRTC[8] =  (pSiS->SiS_Pr->CVSyncStart - 1) & 0xFF;	/* cr10 */
-   pSiS->SiS_Pr->CCRT1CRTC[9] =  ((pSiS->SiS_Pr->CVSyncEnd - 1) & 0x0F) | 0x80;	/* cr11 */
-   pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay - 1) & 0xFF;		/* cr12 */
-   pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF;	/* cr15 */
-   pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd - 1) & 0xFF;		/* cr16 */
-   
-   pSiS->SiS_Pr->CCRT1CRTC[13] = 
+   pSiS->SiS_Pr->CCRT1CRTC[8] =  (pSiS->SiS_Pr->CVSyncStart     ) & 0xFF;		/* cr10 */
+   pSiS->SiS_Pr->CCRT1CRTC[9] =  ((pSiS->SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;	/* cr11 */
+   pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay    - 1) & 0xFF;		/* cr12 */
+   pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF;		/* cr15 */
+   pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd   - 1) & 0xFF;		/* cr16 */
+
+   pSiS->SiS_Pr->CCRT1CRTC[13] =
                         GETBITSTR((pSiS->SiS_Pr->CVTotal     -2), 10:10, 0:0) |
                         GETBITSTR((pSiS->SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
                         GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
                         GETBITSTR((pSiS->SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
                         GETBITSTR((pSiS->SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncEnd   -1),   4:4, 5:5) ;  
+                        GETBITSTR((pSiS->SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
 
-   pSiS->SiS_Pr->CCRT1CRTC[14] = 
+   pSiS->SiS_Pr->CCRT1CRTC[14] =
                         GETBITSTR((pSiS->SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
                         GETBITSTR((pSiS->SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
                         GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
                         GETBITSTR((pSiS->SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
 
-        
+
    pSiS->SiS_Pr->CCRT1CRTC[15] =
                         GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ; 
-			
+                        GETBITSTR((pSiS->SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+
    switch(depth) {
-   case 8: 			
-      	pSiS->SiS_Pr->CModeFlag = 0x223b;
+   case 8:
+      	pSiS->SiS_Pr->CModeFlag |= 0x223b;
 	break;
-   case 16: 			
-      	pSiS->SiS_Pr->CModeFlag = 0x227d;
+   case 16:
+      	pSiS->SiS_Pr->CModeFlag |= 0x227d;
 	break;
-   case 32: 			
-      	pSiS->SiS_Pr->CModeFlag = 0x22ff;
+   case 32:
+      	pSiS->SiS_Pr->CModeFlag |= 0x22ff;
 	break;		
    default: 
    	return 0;	
@@ -5139,9 +5298,9 @@
 	pSiS->SiS_Pr->CModeFlag |= LineCompareOff;
    if(pSiS->SiS_Pr->CFlags & V_CLKDIV2)
         pSiS->SiS_Pr->CModeFlag |= HalfDCLK;
-   
+
    pSiS->SiS_Pr->CInfoFlag = 0x0007;
-   if(pSiS->SiS_Pr->CFlags & V_NHSYNC) 
+   if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
    	pSiS->SiS_Pr->CInfoFlag |= 0x4000;
    if(pSiS->SiS_Pr->CFlags & V_NVSYNC) 
    	pSiS->SiS_Pr->CInfoFlag |= 0x8000;
@@ -5177,13 +5336,13 @@
    	pSiS->SiS_Pr->CSR2B,
 	pSiS->SiS_Pr->CSR2C,
 	pSiS->SiS_Pr->CSRClock);
-#endif   	
+#endif
    return 1;
 }
 
 /* TW: Build a list of supported modes */
 DisplayModePtr
-SiSBuildBuiltInModeList(ScrnInfoPtr pScrn)
+SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi)
 {
    SISPtr         pSiS = SISPTR(pScrn);
    unsigned short VRE, VBE, VRS, VBS, VDE, VT;
@@ -5191,14 +5350,16 @@
    unsigned char  sr_data, cr_data, cr_data2, cr_data3;
    unsigned char  sr2b, sr2c;
    float          num, denum, postscalar, divider;
-   int            A, B, C, D, E, F, temp, i, j, index, vclkindex;
+   int            A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex;
    DisplayModePtr new = NULL, current = NULL, first = NULL;
+   BOOLEAN        done = FALSE;
 #if 0
    DisplayModePtr backup = NULL;
-#endif   
+#endif
 
    pSiS->backupmodelist = NULL;
-   
+   pSiS->AddedPlasmaModes = FALSE;
+
    /* Initialize our pointers */
    if(pSiS->VGAEngine == SIS_300_VGA) {
 #ifdef SIS300
@@ -5222,13 +5383,20 @@
       if(pSiS->VGAEngine == SIS_300_VGA) index &= 0x3F;
 #endif      
 
-      if((!pSiS->DSTN) &&
-	 (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
-	 (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 480))  {
+      /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */
+      if((!pSiS->FSTN) &&
+	 (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a))  {
            i++;
       	   continue;
       }
-      
+      if((pSiS->FSTN) &&
+         (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
+	 (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) &&
+	 (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) {
+	   i++;
+	   continue;
+      }
+
       if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
       memset(new, 0, sizeof(DisplayModeRec));
       if(!(new->name = xalloc(10))) {
@@ -5242,13 +5410,13 @@
       }
 
       current = new;
-      
+
       sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes,
                                       pSiS->SiS_Pr->SiS_RefIndex[i].YRes);
 
       current->status = MODE_OK;
 
-      current->type = M_T_DEFAULT; 
+      current->type = M_T_DEFAULT;
 
       vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK;
       if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F;
@@ -5261,7 +5429,7 @@
               ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0);
       num = (sr2b & 0x7f) + 1.0;
       denum = (sr2c & 0x1f) + 1.0;
-      
+
 #ifdef TWDEBUG
       xf86DrvMsg(0, X_INFO, "------------\n");
       xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n",
@@ -5475,7 +5643,7 @@
 	 current->VSyncStart <<= 1;
 	 current->VSyncEnd <<= 1;
 	 current->VTotal <<= 1;
-	 current->VTotal |= 1; 
+	 current->VTotal |= 1;
       }
       if(current->Flags & V_DBLSCAN) {
          current->Clock >>= 1;
@@ -5517,6 +5685,187 @@
       i++;
    }
 
+   /* Add non-standard LCD modes for panel's detailed timings */
+
+   if(!includelcdmodes) return first;
+
+   xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n",
+      pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product);
+
+   i = 0;
+   while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) {
+
+     if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) {
+
+        for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
+
+	    if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) {
+
+	       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+	       	  "Identified %s panel, adding specific modes\n",
+		  SiS_PlasmaTable[i].plasmaname);
+
+	       for(k=0; k<SiS_PlasmaTable[i].modenum; k++) {
+
+	          if(isfordvi) {
+		     if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue;
+		  } else {
+		     if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue;
+		  }
+
+	          if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
+
+                  memset(new, 0, sizeof(DisplayModeRec));
+                  if(!(new->name = xalloc(10))) {
+      		     xfree(new);
+		     return first;
+                  }
+                  if(!first) first = new;
+                  if(current) {
+                     current->next = new;
+	             new->prev = current;
+                  }
+
+                  current = new;
+
+		  pSiS->AddedPlasmaModes = TRUE;
+
+		  l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f;
+
+	          sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay,
+                                                  SiS_PlasmaMode[l].VDisplay);
+
+                  current->status = MODE_OK;
+
+                  current->type = M_T_BUILTIN;
+
+		  current->Clock = SiS_PlasmaMode[l].clock;
+            	  current->SynthClock = current->Clock;
+
+                  current->HDisplay   = SiS_PlasmaMode[l].HDisplay;
+                  current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch;
+                  current->HSyncEnd   = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth;
+                  current->HTotal     = SiS_PlasmaMode[l].HTotal;
+
+		  current->VDisplay   = SiS_PlasmaMode[l].VDisplay;
+                  current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch;
+                  current->VSyncEnd   = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth;
+                  current->VTotal     = SiS_PlasmaMode[l].VTotal;
+
+                  current->CrtcHDisplay = current->HDisplay;
+                  current->CrtcHBlankStart = current->HSyncStart;
+                  current->CrtcHSyncStart = current->HSyncStart;
+                  current->CrtcHSyncEnd = current->HSyncEnd;
+                  current->CrtcHBlankEnd = current->HSyncEnd;
+                  current->CrtcHTotal = current->HTotal;
+
+                  current->CrtcVDisplay = current->VDisplay;
+                  current->CrtcVBlankStart = current->VSyncStart;
+                  current->CrtcVSyncStart = current->VSyncStart;
+                  current->CrtcVSyncEnd = current->VSyncEnd;
+                  current->CrtcVBlankEnd = current->VSyncEnd;
+                  current->CrtcVTotal = current->VTotal;
+
+                  if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP)
+                     current->Flags |= V_PHSYNC;
+                  else
+                     current->Flags |= V_NHSYNC;
+
+                  if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP)
+                     current->Flags |= V_PVSYNC;
+                  else
+                     current->Flags |= V_NVSYNC;
+
+		  if(current->HDisplay > pSiS->LCDwidth)
+		     pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay;
+	          if(current->VDisplay > pSiS->LCDheight)
+		     pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay;
+
+               }
+	       done = TRUE;
+	       break;
+	    }
+	}
+     }
+
+     i++;
+
+   }
+
+   if(pSiS->SiS_Pr->CP_HaveCustomData) {
+
+      for(i=0; i<7; i++) {
+
+         if(pSiS->SiS_Pr->CP_DataValid[i]) {
+
+            if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
+
+            memset(new, 0, sizeof(DisplayModeRec));
+            if(!(new->name = xalloc(10))) {
+      		xfree(new);
+		return first;
+            }
+            if(!first) first = new;
+            if(current) {
+               current->next = new;
+	       new->prev = current;
+            }
+
+            current = new;
+
+            sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i],
+                                            pSiS->SiS_Pr->CP_VDisplay[i]);
+
+            current->status = MODE_OK;
+
+            current->type = M_T_BUILTIN;
+
+            current->Clock = pSiS->SiS_Pr->CP_Clock[i];
+            current->SynthClock = current->Clock;
+
+            current->HDisplay   = pSiS->SiS_Pr->CP_HDisplay[i];
+            current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i];
+            current->HSyncEnd   = pSiS->SiS_Pr->CP_HSyncEnd[i];
+            current->HTotal     = pSiS->SiS_Pr->CP_HTotal[i];
+
+            current->VDisplay   = pSiS->SiS_Pr->CP_VDisplay[i];
+            current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i];
+            current->VSyncEnd   = pSiS->SiS_Pr->CP_VSyncEnd[i];
+            current->VTotal     = pSiS->SiS_Pr->CP_VTotal[i];
+
+            current->CrtcHDisplay = current->HDisplay;
+            current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i];
+            current->CrtcHSyncStart = current->HSyncStart;
+            current->CrtcHSyncEnd = current->HSyncEnd;
+            current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i];
+            current->CrtcHTotal = current->HTotal;
+
+            current->CrtcVDisplay = current->VDisplay;
+            current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i];
+            current->CrtcVSyncStart = current->VSyncStart;
+            current->CrtcVSyncEnd = current->VSyncEnd;
+            current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i];
+            current->CrtcVTotal = current->VTotal;
+
+	    if(pSiS->SiS_Pr->CP_SyncValid[i]) {
+               if(pSiS->SiS_Pr->CP_HSync_P[i])
+                  current->Flags |= V_PHSYNC;
+               else
+                  current->Flags |= V_NHSYNC;
+
+               if(pSiS->SiS_Pr->CP_VSync_P[i])
+                  current->Flags |= V_PVSYNC;
+               else
+                  current->Flags |= V_NVSYNC;
+	    } else {
+	       /* No sync data? Use positive sync... */
+	       current->Flags |= V_PHSYNC;
+	       current->Flags |= V_PVSYNC;
+	    }
+         }
+      }
+   }
+
    return first;
 
 }
@@ -5533,7 +5882,7 @@
     UCHAR  *ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
     ULONG  temp = 0;
     int    Clock;
-    
+
     if(HwDeviceExtension->jChipType < SIS_315H) {
 #ifdef SIS300
        InitTo300Pointer(SiS_Pr, HwDeviceExtension);
@@ -5565,6 +5914,56 @@
     return(Clock);
 }
 
+BOOLEAN
+sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex)
+{
+    USHORT ModeNo = modeno;
+    USHORT ModeIdIndex = 0, CRT1Index = 0;
+    USHORT RefreshRateTableIndex = 0;
+    UCHAR  *ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
+    ULONG  temp = 0;
+    unsigned char  sr_data, cr_data, cr_data2;
+
+    if(HwDeviceExtension->jChipType < SIS_315H) {
+#ifdef SIS300
+       InitTo300Pointer(SiS_Pr, HwDeviceExtension);
+#else
+       return FALSE;
+#endif
+    } else {
+#ifdef SIS315H
+       InitTo310Pointer(SiS_Pr, HwDeviceExtension);
+#else
+       return FALSE;
+#endif
+    }
+
+    temp = SiS_SearchModeID(SiS_Pr, ROMAddr, &ModeNo, &ModeIdIndex);
+    if(!temp) return FALSE;
+
+    RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+    RefreshRateTableIndex += (rateindex - 1);
+    CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
+    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
+    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+    *vtotal = ((cr_data & 0xFF) |
+               ((unsigned short)(cr_data2 & 0x01) <<  8) |
+	       ((unsigned short)(cr_data2 & 0x20) <<  4) |
+	       ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
+
+    if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode)
+       *vtotal *= 2;
+
+    return TRUE;
+}
+
 int
 sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
 			 unsigned char modeno, unsigned char rateindex,
@@ -5676,9 +6075,9 @@
     sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13];
 
     cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6];
-    
+
     cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7];
-    
+
     /* Vertical total */
     VT = (cr_data & 0xFF) |
          ((unsigned short) (cr_data2 & 0x01) << 8) |

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)