1/* 2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 3 * 4 * Display mode initializing code 5 * 6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 7 * 8 * If distributed as part of the Linux kernel, this code is licensed under the 9 * terms of the GPL v2. 10 * 11 * Otherwise, the following license terms apply: 12 * 13 * * Redistribution and use in source and binary forms, with or without 14 * * modification, are permitted provided that the following conditions 15 * * are met: 16 * * 1) Redistributions of source code must retain the above copyright 17 * * notice, this list of conditions and the following disclaimer. 18 * * 2) Redistributions in binary form must reproduce the above copyright 19 * * notice, this list of conditions and the following disclaimer in the 20 * * documentation and/or other materials provided with the distribution. 21 * * 3) The name of the author may not be used to endorse or promote products 22 * * derived from this software without specific prior written permission. 23 * * 24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * Author: Thomas Winischhofer <thomas@winischhofer.net> 36 * 37 */ 38 39#include <linux/module.h> 40#include <linux/kernel.h> 41#include <linux/errno.h> 42#include <linux/poll.h> 43#include <linux/init.h> 44#include <linux/spinlock.h> 45 46#include "sisusb.h" 47 48#ifdef INCL_SISUSB_CON 49 50#include "sisusb_init.h" 51 52/*********************************************/ 53/* POINTER INITIALIZATION */ 54/*********************************************/ 55 56static void SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) 57{ 58 SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo; 59 SiS_Pr->SiS_StandTable = SiSUSB_StandTable; 60 61 SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable; 62 SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable; 63 SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex; 64 SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table; 65 66 SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData; 67} 68 69/*********************************************/ 70/* HELPER: SetReg, GetReg */ 71/*********************************************/ 72 73static void 74SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port, 75 unsigned short index, unsigned short data) 76{ 77 sisusb_setidxreg(SiS_Pr->sisusb, port, index, data); 78} 79 80static void 81SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port, 82 unsigned short data) 83{ 84 sisusb_setreg(SiS_Pr->sisusb, port, data); 85} 86 87static unsigned char 88SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index) 89{ 90 u8 data; 91 92 sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data); 93 94 return data; 95} 96 97static unsigned char 98SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port) 99{ 100 u8 data; 101 102 sisusb_getreg(SiS_Pr->sisusb, port, &data); 103 104 return data; 105} 106 107static void 108SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port, 109 unsigned short index, unsigned short DataAND, 110 unsigned short DataOR) 111{ 112 sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR); 113} 114 115static void 116SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port, 117 unsigned short index, unsigned short DataAND) 118{ 119 sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND); 120} 121 122static void 123SiS_SetRegOR(struct SiS_Private *SiS_Pr, unsigned long port, 124 unsigned short index, unsigned short DataOR) 125{ 126 sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR); 127} 128 129/*********************************************/ 130/* HELPER: DisplayOn, DisplayOff */ 131/*********************************************/ 132 133static void SiS_DisplayOn(struct SiS_Private *SiS_Pr) 134{ 135 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF); 136} 137 138/*********************************************/ 139/* HELPER: Init Port Addresses */ 140/*********************************************/ 141 142static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) 143{ 144 SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; 145 SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; 146 SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; 147 SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; 148 SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; 149 SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; 150 SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; 151 SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; 152 SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; 153 SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; 154 SiS_Pr->SiS_P3cb = BaseAddr + 0x1b; 155 SiS_Pr->SiS_P3cc = BaseAddr + 0x1c; 156 SiS_Pr->SiS_P3cd = BaseAddr + 0x1d; 157 SiS_Pr->SiS_P3da = BaseAddr + 0x2a; 158 SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; 159} 160 161/*********************************************/ 162/* HELPER: GetSysFlags */ 163/*********************************************/ 164 165static void SiS_GetSysFlags(struct SiS_Private *SiS_Pr) 166{ 167 SiS_Pr->SiS_MyCR63 = 0x63; 168} 169 170/*********************************************/ 171/* HELPER: Init PCI & Engines */ 172/*********************************************/ 173 174static void SiSInitPCIetc(struct SiS_Private *SiS_Pr) 175{ 176 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1); 177 /* - Enable 2D (0x40) 178 * - Enable 3D (0x02) 179 * - Enable 3D vertex command fetch (0x10) 180 * - Enable 3D command parser (0x08) 181 * - Enable 3D G/L transformation engine (0x80) 182 */ 183 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA); 184} 185 186/*********************************************/ 187/* HELPER: SET SEGMENT REGISTERS */ 188/*********************************************/ 189 190static void SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value) 191{ 192 unsigned short temp; 193 194 value &= 0x00ff; 195 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0; 196 temp |= (value >> 4); 197 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); 198 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0; 199 temp |= (value & 0x0f); 200 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); 201} 202 203static void SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value) 204{ 205 unsigned short temp; 206 207 value &= 0x00ff; 208 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f; 209 temp |= (value & 0xf0); 210 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); 211 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f; 212 temp |= (value << 4); 213 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); 214} 215 216static void SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value) 217{ 218 SiS_SetSegRegLower(SiS_Pr, value); 219 SiS_SetSegRegUpper(SiS_Pr, value); 220} 221 222static void SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr) 223{ 224 SiS_SetSegmentReg(SiS_Pr, 0); 225} 226 227static void 228SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value) 229{ 230 unsigned short temp = value >> 8; 231 232 temp &= 0x07; 233 temp |= (temp << 4); 234 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp); 235 SiS_SetSegmentReg(SiS_Pr, value); 236} 237 238static void SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr) 239{ 240 SiS_SetSegmentRegOver(SiS_Pr, 0); 241} 242 243static void SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr) 244{ 245 SiS_ResetSegmentReg(SiS_Pr); 246 SiS_ResetSegmentRegOver(SiS_Pr); 247} 248 249/*********************************************/ 250/* HELPER: SearchModeID */ 251/*********************************************/ 252 253static int 254SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, 255 unsigned short *ModeIdIndex) 256{ 257 if ((*ModeNo) <= 0x13) { 258 259 if ((*ModeNo) != 0x03) 260 return 0; 261 262 (*ModeIdIndex) = 0; 263 264 } else { 265 266 for (*ModeIdIndex = 0;; (*ModeIdIndex)++) { 267 268 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 269 (*ModeNo)) 270 break; 271 272 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 273 0xFF) 274 return 0; 275 } 276 277 } 278 279 return 1; 280} 281 282/*********************************************/ 283/* HELPER: ENABLE CRT1 */ 284/*********************************************/ 285 286static void SiS_HandleCRT1(struct SiS_Private *SiS_Pr) 287{ 288 /* Enable CRT1 gating */ 289 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf); 290} 291 292/*********************************************/ 293/* HELPER: GetColorDepth */ 294/*********************************************/ 295 296static unsigned short 297SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 298 unsigned short ModeIdIndex) 299{ 300 static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 }; 301 unsigned short modeflag; 302 short index; 303 304 if (ModeNo <= 0x13) { 305 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; 306 } else { 307 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 308 } 309 310 index = (modeflag & ModeTypeMask) - ModeEGA; 311 if (index < 0) 312 index = 0; 313 return ColorDepth[index]; 314} 315 316/*********************************************/ 317/* HELPER: GetOffset */ 318/*********************************************/ 319 320static unsigned short 321SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 322 unsigned short ModeIdIndex, unsigned short rrti) 323{ 324 unsigned short xres, temp, colordepth, infoflag; 325 326 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 327 xres = SiS_Pr->SiS_RefIndex[rrti].XRes; 328 329 colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex); 330 331 temp = xres / 16; 332 333 if (infoflag & InterlaceMode) 334 temp <<= 1; 335 336 temp *= colordepth; 337 338 if (xres % 16) 339 temp += (colordepth >> 1); 340 341 return temp; 342} 343 344/*********************************************/ 345/* SEQ */ 346/*********************************************/ 347 348static void 349SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 350{ 351 unsigned char SRdata; 352 int i; 353 354 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03); 355 356 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20; 357 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata); 358 359 for (i = 2; i <= 4; i++) { 360 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1]; 361 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata); 362 } 363} 364 365/*********************************************/ 366/* MISC */ 367/*********************************************/ 368 369static void 370SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 371{ 372 unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; 373 374 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata); 375} 376 377/*********************************************/ 378/* CRTC */ 379/*********************************************/ 380 381static void 382SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 383{ 384 unsigned char CRTCdata; 385 unsigned short i; 386 387 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); 388 389 for (i = 0; i <= 0x18; i++) { 390 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; 391 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata); 392 } 393} 394 395/*********************************************/ 396/* ATT */ 397/*********************************************/ 398 399static void 400SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 401{ 402 unsigned char ARdata; 403 unsigned short i; 404 405 for (i = 0; i <= 0x13; i++) { 406 ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; 407 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 408 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i); 409 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata); 410 } 411 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 412 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14); 413 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00); 414 415 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 416 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20); 417 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 418} 419 420/*********************************************/ 421/* GRC */ 422/*********************************************/ 423 424static void 425SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 426{ 427 unsigned char GRdata; 428 unsigned short i; 429 430 for (i = 0; i <= 0x08; i++) { 431 GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; 432 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata); 433 } 434 435 if (SiS_Pr->SiS_ModeType > ModeVGA) { 436 /* 256 color disable */ 437 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF); 438 } 439} 440 441/*********************************************/ 442/* CLEAR EXTENDED REGISTERS */ 443/*********************************************/ 444 445static void SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 446{ 447 int i; 448 449 for (i = 0x0A; i <= 0x0E; i++) { 450 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00); 451 } 452 453 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE); 454} 455 456/*********************************************/ 457/* Get rate index */ 458/*********************************************/ 459 460static unsigned short 461SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 462 unsigned short ModeIdIndex) 463{ 464 unsigned short rrti, i, index, temp; 465 466 if (ModeNo <= 0x13) 467 return 0xFFFF; 468 469 index = SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x33) & 0x0F; 470 if (index > 0) 471 index--; 472 473 rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; 474 ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID; 475 476 i = 0; 477 do { 478 if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo) 479 break; 480 481 temp = 482 SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask; 483 if (temp < SiS_Pr->SiS_ModeType) 484 break; 485 486 i++; 487 index--; 488 } while (index != 0xFFFF); 489 490 i--; 491 492 return (rrti + i); 493} 494 495/*********************************************/ 496/* SYNC */ 497/*********************************************/ 498 499static void SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti) 500{ 501 unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8; 502 sync &= 0xC0; 503 sync |= 0x2f; 504 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync); 505} 506 507/*********************************************/ 508/* CRTC/2 */ 509/*********************************************/ 510 511static void 512SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 513 unsigned short ModeIdIndex, unsigned short rrti) 514{ 515 unsigned char index; 516 unsigned short temp, i, j, modeflag; 517 518 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); 519 520 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 521 522 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC; 523 524 for (i = 0, j = 0; i <= 7; i++, j++) { 525 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 526 SiS_Pr->SiS_CRT1Table[index].CR[i]); 527 } 528 for (j = 0x10; i <= 10; i++, j++) { 529 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 530 SiS_Pr->SiS_CRT1Table[index].CR[i]); 531 } 532 for (j = 0x15; i <= 12; i++, j++) { 533 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 534 SiS_Pr->SiS_CRT1Table[index].CR[i]); 535 } 536 for (j = 0x0A; i <= 15; i++, j++) { 537 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j, 538 SiS_Pr->SiS_CRT1Table[index].CR[i]); 539 } 540 541 temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; 542 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, temp); 543 544 temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; 545 if (modeflag & DoubleScanMode) 546 temp |= 0x80; 547 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp); 548 549 if (SiS_Pr->SiS_ModeType > ModeVGA) 550 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F); 551} 552 553/*********************************************/ 554/* OFFSET & PITCH */ 555/*********************************************/ 556/* (partly overruled by SetPitch() in XF86) */ 557/*********************************************/ 558 559static void 560SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 561 unsigned short ModeIdIndex, unsigned short rrti) 562{ 563 unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti); 564 unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 565 unsigned short temp; 566 567 temp = (du >> 8) & 0x0f; 568 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp); 569 570 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF)); 571 572 if (infoflag & InterlaceMode) 573 du >>= 1; 574 575 du <<= 5; 576 temp = (du >> 8) & 0xff; 577 if (du & 0xff) 578 temp++; 579 temp++; 580 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp); 581} 582 583/*********************************************/ 584/* VCLK */ 585/*********************************************/ 586 587static void 588SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 589 unsigned short rrti) 590{ 591 unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; 592 unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B; 593 unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C; 594 595 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xCF); 596 597 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2B, clka); 598 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2C, clkb); 599 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2D, 0x01); 600} 601 602/*********************************************/ 603/* FIFO */ 604/*********************************************/ 605 606static void 607SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 608 unsigned short mi) 609{ 610 unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; 611 612 /* disable auto-threshold */ 613 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE); 614 615 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE); 616 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0); 617 618 if (ModeNo <= 0x13) 619 return; 620 621 if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { 622 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34); 623 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01); 624 } 625} 626 627/*********************************************/ 628/* MODE REGISTERS */ 629/*********************************************/ 630 631static void 632SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 633 unsigned short rrti) 634{ 635 unsigned short data = 0, VCLK = 0, index = 0; 636 637 if (ModeNo > 0x13) { 638 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; 639 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; 640 } 641 642 if (VCLK >= 166) 643 data |= 0x0c; 644 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data); 645 646 if (VCLK >= 166) 647 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7); 648 649 /* DAC speed */ 650 data = 0x03; 651 if (VCLK >= 260) 652 data = 0x00; 653 else if (VCLK >= 160) 654 data = 0x01; 655 else if (VCLK >= 135) 656 data = 0x02; 657 658 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data); 659} 660 661static void 662SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 663 unsigned short ModeIdIndex, unsigned short rrti) 664{ 665 unsigned short data, infoflag = 0, modeflag; 666 667 if (ModeNo <= 0x13) 668 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; 669 else { 670 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 671 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 672 } 673 674 /* Disable DPMS */ 675 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F); 676 677 data = 0; 678 if (ModeNo > 0x13) { 679 if (SiS_Pr->SiS_ModeType > ModeEGA) { 680 data |= 0x02; 681 data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); 682 } 683 if (infoflag & InterlaceMode) 684 data |= 0x20; 685 } 686 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data); 687 688 data = 0; 689 if (infoflag & InterlaceMode) { 690 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */ 691 unsigned short hrs = 692 (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) | 693 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) 694 - 3; 695 unsigned short hto = 696 (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) | 697 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) 698 + 5; 699 data = hrs - (hto >> 1) + 3; 700 } 701 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF)); 702 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8)); 703 704 if (modeflag & HalfDCLK) 705 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08); 706 707 data = 0; 708 if (modeflag & LineCompareOff) 709 data = 0x08; 710 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data); 711 712 if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13)) 713 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40); 714 715 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb); 716 717 data = 0x60; 718 if (SiS_Pr->SiS_ModeType != ModeText) { 719 data ^= 0x60; 720 if (SiS_Pr->SiS_ModeType != ModeEGA) 721 data ^= 0xA0; 722 } 723 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data); 724 725 SiS_SetVCLKState(SiS_Pr, ModeNo, rrti); 726 727 if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40) 728 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c); 729 else 730 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c); 731} 732 733/*********************************************/ 734/* LOAD DAC */ 735/*********************************************/ 736 737static void 738SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData, 739 unsigned short shiftflag, unsigned short dl, unsigned short ah, 740 unsigned short al, unsigned short dh) 741{ 742 unsigned short d1, d2, d3; 743 744 switch (dl) { 745 case 0: 746 d1 = dh; 747 d2 = ah; 748 d3 = al; 749 break; 750 case 1: 751 d1 = ah; 752 d2 = al; 753 d3 = dh; 754 break; 755 default: 756 d1 = al; 757 d2 = dh; 758 d3 = ah; 759 } 760 SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag)); 761 SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag)); 762 SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag)); 763} 764 765static void 766SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 767 unsigned short mi) 768{ 769 unsigned short data, data2, time, i, j, k, m, n, o; 770 unsigned short si, di, bx, sf; 771 unsigned long DACAddr, DACData; 772 const unsigned char *table = NULL; 773 774 if (ModeNo < 0x13) 775 data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag; 776 else 777 data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; 778 779 data &= DACInfoFlag; 780 781 j = time = 64; 782 if (data == 0x00) 783 table = SiS_MDA_DAC; 784 else if (data == 0x08) 785 table = SiS_CGA_DAC; 786 else if (data == 0x10) 787 table = SiS_EGA_DAC; 788 else { 789 j = 16; 790 time = 256; 791 table = SiS_VGA_DAC; 792 } 793 794 DACAddr = SiS_Pr->SiS_P3c8; 795 DACData = SiS_Pr->SiS_P3c9; 796 sf = 0; 797 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF); 798 799 SiS_SetRegByte(SiS_Pr, DACAddr, 0x00); 800 801 for (i = 0; i < j; i++) { 802 data = table[i]; 803 for (k = 0; k < 3; k++) { 804 data2 = 0; 805 if (data & 0x01) 806 data2 += 0x2A; 807 if (data & 0x02) 808 data2 += 0x15; 809 SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf)); 810 data >>= 2; 811 } 812 } 813 814 if (time == 256) { 815 for (i = 16; i < 32; i++) { 816 data = table[i] << sf; 817 for (k = 0; k < 3; k++) 818 SiS_SetRegByte(SiS_Pr, DACData, data); 819 } 820 si = 32; 821 for (m = 0; m < 9; m++) { 822 di = si; 823 bx = si + 4; 824 for (n = 0; n < 3; n++) { 825 for (o = 0; o < 5; o++) { 826 SiS_WriteDAC(SiS_Pr, DACData, sf, n, 827 table[di], table[bx], 828 table[si]); 829 si++; 830 } 831 si -= 2; 832 for (o = 0; o < 3; o++) { 833 SiS_WriteDAC(SiS_Pr, DACData, sf, n, 834 table[di], table[si], 835 table[bx]); 836 si--; 837 } 838 } 839 si += 5; 840 } 841 } 842} 843 844/*********************************************/ 845/* SET CRT1 REGISTER GROUP */ 846/*********************************************/ 847 848static void 849SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 850 unsigned short ModeIdIndex) 851{ 852 unsigned short StandTableIndex, rrti; 853 854 SiS_Pr->SiS_CRT1Mode = ModeNo; 855 856 if (ModeNo <= 0x13) 857 StandTableIndex = 0; 858 else 859 StandTableIndex = 1; 860 861 SiS_ResetSegmentRegisters(SiS_Pr); 862 SiS_SetSeqRegs(SiS_Pr, StandTableIndex); 863 SiS_SetMiscRegs(SiS_Pr, StandTableIndex); 864 SiS_SetCRTCRegs(SiS_Pr, StandTableIndex); 865 SiS_SetATTRegs(SiS_Pr, StandTableIndex); 866 SiS_SetGRCRegs(SiS_Pr, StandTableIndex); 867 SiS_ClearExt1Regs(SiS_Pr, ModeNo); 868 869 rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex); 870 871 if (rrti != 0xFFFF) { 872 SiS_SetCRT1Sync(SiS_Pr, rrti); 873 SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti); 874 SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti); 875 SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti); 876 } 877 878 SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex); 879 880 SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti); 881 882 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex); 883 884 SiS_DisplayOn(SiS_Pr); 885} 886 887/*********************************************/ 888/* SiSSetMode() */ 889/*********************************************/ 890 891int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 892{ 893 unsigned short ModeIdIndex; 894 unsigned long BaseAddr = SiS_Pr->IOAddress; 895 896 SiSUSB_InitPtr(SiS_Pr); 897 SiSUSBRegInit(SiS_Pr, BaseAddr); 898 SiS_GetSysFlags(SiS_Pr); 899 900 if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) 901 return 0; 902 903 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86); 904 905 SiSInitPCIetc(SiS_Pr); 906 907 ModeNo &= 0x7f; 908 909 SiS_Pr->SiS_ModeType = 910 SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask; 911 912 SiS_Pr->SiS_SetFlag = LowModeTests; 913 914 /* Set mode on CRT1 */ 915 SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex); 916 917 SiS_HandleCRT1(SiS_Pr); 918 919 SiS_DisplayOn(SiS_Pr); 920 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF); 921 922 /* Store mode number */ 923 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo); 924 925 return 1; 926} 927 928int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo) 929{ 930 unsigned short ModeNo = 0; 931 int i; 932 933 SiSUSB_InitPtr(SiS_Pr); 934 935 if (VModeNo == 0x03) { 936 937 ModeNo = 0x03; 938 939 } else { 940 941 i = 0; 942 do { 943 944 if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) { 945 ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID; 946 break; 947 } 948 949 } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff); 950 951 } 952 953 if (!ModeNo) 954 return 0; 955 956 return SiSUSBSetMode(SiS_Pr, ModeNo); 957} 958 959#endif /* INCL_SISUSB_CON */ 960