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