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