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