init.c revision dfe64dd3
1/* 2 * Mode initializing code (CRT1 section) 3 * (Universal module for Linux kernel framebuffer and XFree86 4.x) 4 * 5 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria 6 * 7 * If distributed as part of the Linux kernel, the following license terms 8 * apply: 9 * 10 * * This program is free software; you can redistribute it and/or modify 11 * * it under the terms of the GNU General Public License as published by 12 * * the Free Software Foundation; either version 2 of the named License, 13 * * or any later version. 14 * * 15 * * This program is distributed in the hope that it will be useful, 16 * * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * * GNU General Public License for more details. 19 * * 20 * * You should have received a copy of the GNU General Public License 21 * * along with this program; if not, write to the Free Software 22 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 23 * 24 * Otherwise, the following license terms apply: 25 * 26 * * Redistribution and use in source and binary forms, with or without 27 * * modification, are permitted provided that the following conditions 28 * * are met: 29 * * 1) Redistributions of source code must retain the above copyright 30 * * notice, this list of conditions and the following disclaimer. 31 * * 2) Redistributions in binary form must reproduce the above copyright 32 * * notice, this list of conditions and the following disclaimer in the 33 * * documentation and/or other materials provided with the distribution. 34 * * 3) The name of the author may not be used to endorse or promote products 35 * * derived from this software without specific prior written permission. 36 * * 37 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 38 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 40 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 41 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 43 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 44 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 46 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 * 48 * Author: Thomas Winischhofer <thomas@winischhofer.net> 49 * 50 * Formerly based on non-functional code-fragements for 300 series by XGI, Inc. 51 * Used by permission. 52 * 53 * TW says: This code looks awful, I know. But please don't do anything about 54 * this otherwise debugging will be hell. 55 * The code is extremely fragile as regards the different chipsets, different 56 * video bridges and combinations thereof. If anything is changed, extreme 57 * care has to be taken that that change doesn't break it for other chipsets, 58 * bridges or combinations thereof. 59 * All comments in this file are by me, regardless if they are marked TW or not. 60 * 61 */ 62 63#ifdef HAVE_CONFIG_H 64#include "config.h" 65#endif 66 67#include "init.h" 68#include "vgatypes.h" 69#include "vb_def.h" 70#include "vb_setmode.h" 71 72/*********************************************/ 73/* HELPER: Get ModeID */ 74/*********************************************/ 75/* Jong 09/18/2007; patch to GIT */ 76/* VGAEngine is not used; FSTN is always FALSE */ 77USHORT 78XGI_GetModeID(ULONG VBFlags, int HDisplay, int VDisplay, 79 int Depth, int LCDwidth, int LCDheight) 80{ 81 USHORT ModeIndex = 0; 82 83 switch(HDisplay) 84 { 85 case 320: 86 if(VDisplay == 200) 87 ModeIndex = ModeIndex_320x200[Depth]; 88 else if(VDisplay == 240) 89 { 90 ModeIndex = ModeIndex_320x240[Depth]; 91 } 92 break; 93 case 400: 94 if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; 95 break; 96 case 512: 97 if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; 98 break; 99 case 640: 100 if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; 101 else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; 102 break; 103 case 720: 104 if(!(VBFlags & CRT1_LCDA)) { 105 if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; 106 else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; 107 } 108 break; 109 case 768: 110 if(!(VBFlags & CRT1_LCDA)) { 111 if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; 112 } 113 break; 114 case 800: 115 if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; 116 else if(!(VBFlags & CRT1_LCDA)) { 117 if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; 118 } 119 break; 120 case 848: 121 if(!(VBFlags & CRT1_LCDA)) { 122 if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; 123 } 124 break; 125 case 856: 126 if(!(VBFlags & CRT1_LCDA)) { 127 if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; 128 } 129 break; 130 case 1024: 131 if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; 132 else if(!(VBFlags & CRT1_LCDA)) { 133 if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; 134 } 135 break; 136 case 1152: 137 if(!(VBFlags & CRT1_LCDA)) { 138 if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; 139 } 140 break; 141 case 1280: 142 if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; 143 else if(VDisplay == 720) { 144 if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 720)) { 145 ModeIndex = ModeIndex_1280x720[Depth]; 146 } else if(!(VBFlags & CRT1_LCDA)) { 147 ModeIndex = ModeIndex_1280x720[Depth]; 148 } 149 } else if(!(VBFlags & CRT1_LCDA)) { 150 if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth]; 151 else if(VDisplay == 768) { 152 ModeIndex = ModeIndex_310_1280x768[Depth]; 153 } 154 } 155 break; 156 case 1360: 157 if(!(VBFlags & CRT1_LCDA)) { 158 if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; 159 } 160 break; 161 case 1400: 162 break; 163 case 1440: 164 /* if(VDisplay == 900) ModeIndex = ModeIndex_1440x900[Depth]; */ 165 break; 166 case 1600: 167 if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; 168 break; 169 case 1680: 170 break; 171 case 1920: 172 if(!(VBFlags & CRT1_LCDA)) { 173 if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth]; 174 } 175 break; 176 case 2048: 177 if(!(VBFlags & CRT1_LCDA)) { 178 if(VDisplay == 1536) { 179 ModeIndex = ModeIndex_310_2048x1536[Depth]; 180 } 181 } 182 break; 183 } 184 185 return(ModeIndex); 186} 187 188/*********************************************/ 189/* HELPER: SetReg, GetReg */ 190/*********************************************/ 191 192void 193XGI_SetReg(XGIIOADDRESS port, USHORT index, USHORT data) 194{ 195 outb(port,index); 196 outb(port + 1,data); 197} 198 199void 200XGI_SetRegByte(XGIIOADDRESS port, USHORT data) 201{ 202 outb(port,data); 203} 204 205void 206XGI_SetRegShort(XGIIOADDRESS port, USHORT data) 207{ 208 outw(port,data); 209} 210 211void 212XGI_SetRegLong(XGIIOADDRESS port, ULONG data) 213{ 214 outl(port,data); 215} 216 217UCHAR 218XGI_GetReg(XGIIOADDRESS port, USHORT index) 219{ 220 outb(port,index); 221 return inb(port + 1); 222} 223 224UCHAR 225XGI_GetRegByte(XGIIOADDRESS port) 226{ 227 return inb(port); 228} 229 230USHORT 231XGI_GetRegShort(XGIIOADDRESS port) 232{ 233 return inw(port); 234} 235 236ULONG 237XGI_GetRegLong(XGIIOADDRESS port) 238{ 239 return inl(port); 240} 241 242void 243XGI_SetRegANDOR(XGIIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR) 244{ 245 USHORT temp; 246 247 temp = XGI_GetReg(Port,Index); 248 temp = (temp & (DataAND)) | DataOR; 249 XGI_SetReg(Port,Index,temp); 250} 251 252void 253XGI_SetRegAND(XGIIOADDRESS Port,USHORT Index,USHORT DataAND) 254{ 255 USHORT temp; 256 257 temp = XGI_GetReg(Port,Index); 258 temp &= DataAND; 259 XGI_SetReg(Port,Index,temp); 260} 261 262void 263XGI_SetRegOR(XGIIOADDRESS Port,USHORT Index,USHORT DataOR) 264{ 265 USHORT temp; 266 267 temp = XGI_GetReg(Port,Index); 268 temp |= DataOR; 269 XGI_SetReg(Port,Index,temp); 270} 271 272/*********************************************/ 273/* HELPER: DisplayOn, DisplayOff */ 274/*********************************************/ 275 276void 277XGI_New_DisplayOn(VB_DEVICE_INFO *XGI_Pr) 278{ 279 XGI_SetRegAND(XGI_Pr->P3c4,0x01,0xDF); 280} 281 282void 283XGI_New_DisplayOff(VB_DEVICE_INFO *XGI_Pr) 284{ 285 XGI_SetRegOR(XGI_Pr->P3c4,0x01,0x20); 286} 287 288/*********************************************/ 289/* HELPER: Init PCI & Engines */ 290/*********************************************/ 291 292static void 293XGIInitPCIetc(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo) 294{ 295 CARD8 bForce=0x00; /* Jong 01/07/2008; force to disable 2D */ 296 297 switch(HwInfo->jChipType) { 298 case XG40: 299 case XG42: 300 case XG20: 301 case XG21: 302 XGI_SetReg(XGI_Pr->P3c4,0x20,0xa1); 303 /* - Enable 2D (0x40) 304 * - Enable 3D (0x02) 305 * - Enable 3D vertex command fetch (0x10) 306 * - Enable 3D command parser (0x08) 307 * - Enable 3D G/L transformation engine (0x80) 308 */ 309 XGI_SetRegOR(XGI_Pr->P3c4, 0x1E, 310 SR1E_ENABLE_3D_TRANSFORM_ENGINE 311 | SR1E_ENABLE_2D 312 | SR1E_ENABLE_3D_AGP_VERTEX_FETCH 313 | SR1E_ENABLE_3D_COMMAND_PARSER 314 | SR1E_ENABLE_3D); 315 316 /* Jong 01/07/2008; support forcing to disable 2D engine */ 317 if(HwInfo->jChipType == XG21) 318 { 319 inXGIIDXREG(XGI_Pr->P3c4, 0x3A, bForce) ; 320 bForce &= 0x40; 321 322 if(bForce != 0x00) 323 XGI_SetRegAND(XGI_Pr->P3c4,0x1E,0xBF); 324 } 325 326 break; 327 } 328} 329 330/*********************************************/ 331/* HELPER: GetVBType */ 332/*********************************************/ 333 334void 335XGI_New_GetVBType(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo) 336{ 337 USHORT flag=0, rev=0, nolcd=0; 338 339 XGI_Pr->VBType = 0; 340 341 flag = XGI_GetReg(XGI_Pr->Part4Port,0x00); 342PDEBUG(ErrorF("GetVBType: part4_0: %x \n",flag)); //yilin 343 if(flag > 3) return; 344 345 rev = XGI_GetReg(XGI_Pr->Part4Port,0x01); 346PDEBUG(ErrorF("GetVBType: part4_1: %x \n",rev)); //yilin 347 348 if(flag >= 2) { 349 XGI_Pr->VBType = VB_XGI302B; 350 } else if(flag == 1) { 351 if(rev >= 0xC0) { 352 XGI_Pr->VBType = VB_XGI301C; 353 } else if(rev >= 0xB0) { 354 XGI_Pr->VBType = VB_XGI301B; 355 /* Check if 30xB DH version (no LCD support, use Panel Link instead) */ 356 nolcd = XGI_GetReg(XGI_Pr->Part4Port,0x23); 357 if(!(nolcd & 0x02)) XGI_Pr->VBType |= VB_NoLCD; 358 } else { 359 XGI_Pr->VBType = VB_XGI301; 360 } 361 } 362 if(XGI_Pr->VBType & (VB_XGI301B | VB_XGI301C | VB_XGI302B)) { 363 if(rev >= 0xE0) { 364 flag = XGI_GetReg(XGI_Pr->Part4Port,0x39); 365 if(flag == 0xff) XGI_Pr->VBType = VB_XGI302LV; 366 else XGI_Pr->VBType = VB_XGI302ELV; 367 } else if(rev >= 0xD0) { 368 XGI_Pr->VBType = VB_XGI301LV; 369 } 370 } 371PDEBUG(ErrorF("GetVBType: XGI_Pr->VBType=%x \n",XGI_Pr->VBType)); //yilin 372} 373 374/*********************************************/ 375/* HELPER: SearchModeID */ 376/*********************************************/ 377 378BOOLEAN 379XGI_SearchModeID(const XGI_StStruct *SModeIDTable, 380 const XGI_ExtStruct *EModeIDTable, 381 unsigned char VGAINFO, USHORT *ModeNo, USHORT *ModeIdIndex) 382{ 383 if (*ModeNo <= 0x13) { 384 if ((*ModeNo) <= 0x05) 385 (*ModeNo) |= 0x01; 386 387 for (*ModeIdIndex = 0; /* emtpy */; (*ModeIdIndex)++) { 388 if (SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) 389 break; 390 391 if (SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) 392 return FALSE; 393 } 394 395 if (*ModeNo == 0x07) { 396 if (VGAINFO & 0x10) 397 (*ModeIdIndex)++; /* 400 lines */ 398 /* else 350 lines */ 399 } 400 401 if (*ModeNo <= 0x03) { 402 if (!(VGAINFO & 0x80)) 403 (*ModeIdIndex)++; 404 405 if (VGAINFO & 0x10) 406 (*ModeIdIndex)++; /* 400 lines */ 407 /* else 350 lines */ 408 } 409 /* else 200 lines */ 410 } 411 else { 412 413 for (*ModeIdIndex = 0; /* emtpy */; (*ModeIdIndex)++) { 414 if (EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) 415 break; 416 417 if (EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) 418 return FALSE; 419 } 420 } 421 422 return TRUE; 423} 424 425/*********************************************/ 426/* HELPER: GetModePtr */ 427/*********************************************/ 428 429UCHAR 430XGI_GetModePtr(const XGI_StStruct *SModeIDTable, unsigned ModeType, 431 USHORT ModeNo, USHORT ModeIdIndex) 432{ 433 return (ModeNo <= 0x13) 434 ? SModeIDTable[ModeIdIndex].St_StTableIndex 435 : ((ModeType <= 0x02) ? 0x1B /* 02 -> ModeEGA */ : 0x0F); 436} 437 438 439/*********************************************/ 440/* HELPER: LowModeTests */ 441/*********************************************/ 442 443static BOOLEAN 444XGI_DoLowModeTest(VB_DEVICE_INFO *XGI_Pr, USHORT ModeNo, PXGI_HW_DEVICE_INFO HwInfo) 445{ 446 USHORT temp,temp1,temp2; 447 448 if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12)) 449 return(1); 450 temp = XGI_GetReg(XGI_Pr->P3d4,0x11); 451 XGI_SetRegOR(XGI_Pr->P3d4,0x11,0x80); 452 temp1 = XGI_GetReg(XGI_Pr->P3d4,0x00); 453 XGI_SetReg(XGI_Pr->P3d4,0x00,0x55); 454 temp2 = XGI_GetReg(XGI_Pr->P3d4,0x00); 455 XGI_SetReg(XGI_Pr->P3d4,0x00,temp1); 456 XGI_SetReg(XGI_Pr->P3d4,0x11,temp); 457 if (temp2 == 0x55) 458 return(0); 459 else 460 return(1); 461} 462 463static void 464XGI_SetLowModeTest(VB_DEVICE_INFO *XGI_Pr, USHORT ModeNo, PXGI_HW_DEVICE_INFO HwInfo) 465{ 466 if(XGI_DoLowModeTest(XGI_Pr, ModeNo, HwInfo)) { 467 XGI_Pr->SetFlag |= LowModeTests; 468 } 469} 470 471static void 472XGI_HandleCRT1(VB_DEVICE_INFO *XGI_Pr) 473{ 474 XGI_SetRegAND(XGI_Pr->P3d4, 0x53, 0xbf); 475} 476 477/*********************************************/ 478/* HELPER: GetOffset */ 479/*********************************************/ 480 481USHORT 482XGI_New_GetOffset(VB_DEVICE_INFO *XGI_Pr,USHORT ModeNo,USHORT ModeIdIndex, 483 USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwInfo) 484{ 485 USHORT xres, temp, colordepth, infoflag; 486 487 infoflag = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag; 488 xres = XGI_Pr->RefIndex[RefreshRateTableIndex].XRes; 489 490 colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, XGI_Pr); 491 492 temp = xres / 16; 493 if(infoflag & InterlaceMode) temp <<= 1; 494 temp *= colordepth; 495 if(xres % 16) { 496 colordepth >>= 1; 497 temp += colordepth; 498 } 499 500 return(temp); 501} 502 503/*********************************************/ 504/* RESET VCLK */ 505/*********************************************/ 506 507static void 508XGI_ResetCRT1VCLK(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo) 509{ 510 XGI_SetRegANDOR(XGI_Pr->P3c4,0x31,0xCF,0x20); 511 XGI_SetReg(XGI_Pr->P3c4,0x2B,XGI_Pr->VCLKData[1].SR2B); 512 XGI_SetReg(XGI_Pr->P3c4,0x2C,XGI_Pr->VCLKData[1].SR2C); 513 XGI_SetReg(XGI_Pr->P3c4,0x2D,0x80); 514 XGI_SetRegANDOR(XGI_Pr->P3c4,0x31,0xcf,0x10); 515 XGI_SetReg(XGI_Pr->P3c4,0x2B,XGI_Pr->VCLKData[0].SR2B); 516 XGI_SetReg(XGI_Pr->P3c4,0x2C,XGI_Pr->VCLKData[0].SR2C); 517 XGI_SetReg(XGI_Pr->P3c4,0x2D,0x80); 518} 519 520/*********************************************/ 521/* CRTC/2 */ 522/*********************************************/ 523 524static void 525XGI_New_SetCRT1CRTC(VB_DEVICE_INFO *XGI_Pr, USHORT ModeNo, USHORT ModeIdIndex, 526 USHORT RefreshRateTableIndex, 527 PXGI_HW_DEVICE_INFO HwInfo) 528{ 529 UCHAR index; 530 USHORT temp,i,j,modeflag; 531 532 XGI_SetRegAND(XGI_Pr->P3d4,0x11,0x7f); /* unlock cr0-7 */ 533 534 if(ModeNo <= 0x13) { 535 modeflag = XGI_Pr->SModeIDTable[ModeIdIndex].St_ModeFlag; 536 } else { 537 modeflag = XGI_Pr->EModeIDTable[ModeIdIndex].Ext_ModeFlag; 538 } 539 540 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; 541 542 for(i=0,j=0;i<=7;i++,j++) { 543 XGI_SetReg(XGI_Pr->P3d4,j,XGI_Pr->XGINEWUB_CRT1Table[index].CR[i]); 544 } 545 for(j=0x10;i<=10;i++,j++) { 546 XGI_SetReg(XGI_Pr->P3d4,j,XGI_Pr->XGINEWUB_CRT1Table[index].CR[i]); 547 } 548 for(j=0x15;i<=12;i++,j++) { 549 XGI_SetReg(XGI_Pr->P3d4,j,XGI_Pr->XGINEWUB_CRT1Table[index].CR[i]); 550 } 551 for(j=0x0A;i<=15;i++,j++) { 552 XGI_SetReg(XGI_Pr->P3c4,j,XGI_Pr->XGINEWUB_CRT1Table[index].CR[i]); 553 } 554 555 temp = XGI_Pr->XGINEWUB_CRT1Table[index].CR[16] & 0xE0; 556 XGI_SetReg(XGI_Pr->P3c4,0x0E,temp); 557 558 temp = ((XGI_Pr->XGINEWUB_CRT1Table[index].CR[16]) & 0x01) << 5; 559 if(modeflag & DoubleScanMode) temp |= 0x80; 560 XGI_SetRegANDOR(XGI_Pr->P3d4,0x09,0x5F,temp); 561 562 if(XGI_Pr->ModeType > ModeVGA) XGI_SetReg(XGI_Pr->P3d4,0x14,0x4F); 563} 564 565/*********************************************/ 566/* OFFSET & PITCH */ 567/*********************************************/ 568/* (partly overruled by SetPitch() in XF86) */ 569/*********************************************/ 570 571static void 572XGI_New_SetCRT1Offset(VB_DEVICE_INFO *XGI_Pr, USHORT ModeNo, USHORT ModeIdIndex, 573 USHORT RefreshRateTableIndex, 574 PXGI_HW_DEVICE_INFO HwInfo) 575{ 576 USHORT temp, DisplayUnit, infoflag; 577 578 infoflag = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag; 579 580 DisplayUnit = XGI_New_GetOffset(XGI_Pr,ModeNo,ModeIdIndex, 581 RefreshRateTableIndex,HwInfo); 582 583 temp = (DisplayUnit >> 8) & 0x0f; 584 XGI_SetRegANDOR(XGI_Pr->P3c4,0x0E,0xF0,temp); 585 586 temp = DisplayUnit & 0xFF; 587 XGI_SetReg(XGI_Pr->P3d4,0x13,temp); 588 589 if(infoflag & InterlaceMode) DisplayUnit >>= 1; 590 591 DisplayUnit <<= 5; 592 temp = (DisplayUnit & 0xff00) >> 8; 593 if(DisplayUnit & 0xff) temp++; 594 temp++; 595 XGI_SetReg(XGI_Pr->P3c4,0x10,temp); 596} 597 598/*********************************************/ 599/* VCLK */ 600/*********************************************/ 601 602static void 603XGI_New_SetCRT1VCLK(VB_DEVICE_INFO *XGI_Pr, USHORT ModeNo, USHORT ModeIdIndex, 604 PXGI_HW_DEVICE_INFO HwInfo, USHORT RefreshRateTableIndex) 605{ 606 USHORT index=0, clka, clkb; 607 608 if((XGI_Pr->VBType & VB_XGI301BLV302BLV) && (XGI_Pr->VBInfo & SetCRT2ToLCDA)) { 609 clka = XGI_Pr->VBVCLKData[index].Part4_A; 610 clkb = XGI_Pr->VBVCLKData[index].Part4_B; 611 } else { 612 clka = XGI_Pr->VCLKData[index].SR2B; 613 clkb = XGI_Pr->VCLKData[index].SR2C; 614 } 615 616 XGI_SetRegAND(XGI_Pr->P3c4,0x31,0xCF); 617 XGI_SetReg(XGI_Pr->P3c4,0x2B,clka); 618 XGI_SetReg(XGI_Pr->P3c4,0x2C,clkb); 619 XGI_SetReg(XGI_Pr->P3c4,0x2D,0x01); 620} 621 622/*********************************************/ 623/* MODE REGISTERS */ 624/*********************************************/ 625 626static void 627XGI_New_SetVCLKState(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 628 USHORT ModeNo, USHORT RefreshRateTableIndex, 629 USHORT ModeIdIndex) 630{ 631 USHORT data=0, VCLK=0, index=0; 632 633 if(ModeNo > 0x13) { 634 VCLK = XGI_Pr->VCLKData[index].CLOCK; 635 } 636 637 if(VCLK >= 166) 638 data |= 0x0c; 639 640 XGI_SetRegANDOR(XGI_Pr->P3c4,0x32,0xf3,data); 641 642 if(VCLK >= 166) { 643 XGI_SetRegAND(XGI_Pr->P3c4,0x1f,0xe7); 644 } 645 646 /* DAC speed */ 647 XGI_SetRegANDOR(XGI_Pr->P3c4,0x07,0xE8,0x10); 648} 649 650static void 651XGI_New_SetCRT1ModeRegs(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 652 USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex) 653{ 654 USHORT data,infoflag=0,modeflag; 655 USHORT resindex = 0,xres; 656 657 if(ModeNo > 0x13) { 658 modeflag = XGI_Pr->EModeIDTable[ModeIdIndex].Ext_ModeFlag; 659 infoflag = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag; 660 xres = XGI_Pr->ModeResInfo[resindex].HTotal; 661 } else { 662 modeflag = XGI_Pr->SModeIDTable[ModeIdIndex].St_ModeFlag; 663 xres = XGI_Pr->StResInfo[resindex].HTotal; 664 } 665 666 /* Disable DPMS */ 667 XGI_SetRegAND(XGI_Pr->P3c4,0x1F,0x3F); 668 669 data = 0; 670 if(ModeNo > 0x13) { 671 if(XGI_Pr->ModeType > 0x02) { 672 data |= 0x02; 673 data |= ((XGI_Pr->ModeType - ModeVGA) << 2); 674 } 675 if(infoflag & InterlaceMode) data |= 0x20; 676 } 677 XGI_SetRegANDOR(XGI_Pr->P3c4,0x06,0xC0,data); 678 679 data = 0; 680 if(infoflag & InterlaceMode) { 681 if(xres <= 800) data = 0x0020; 682 else if(xres <= 1024) data = 0x0035; 683 else data = 0x0048; 684 } 685 XGI_SetReg(XGI_Pr->P3d4,0x19,(data & 0xFF)); 686 XGI_SetRegANDOR(XGI_Pr->P3d4,0x1a,0xFC,(data >> 8)); 687 688 if(modeflag & HalfDCLK) { 689 XGI_SetRegOR(XGI_Pr->P3c4,0x01,0x08); 690 } 691 692 data = 0; 693 if(modeflag & LineCompareOff) data = 0x08; 694 695 XGI_SetRegANDOR(XGI_Pr->P3c4,0x0F,0xB7,data); 696 if(XGI_Pr->ModeType == ModeEGA) { 697 if(ModeNo > 0x13) { 698 XGI_SetRegOR(XGI_Pr->P3c4,0x0F,0x40); 699 } 700 } 701 702 XGI_SetRegAND(XGI_Pr->P3c4,0x31,0xfb); 703 704 data = 0x60; 705 if(XGI_Pr->ModeType != ModeText) { 706 data ^= 0x60; 707 if(XGI_Pr->ModeType != ModeEGA) { 708 data ^= 0xA0; 709 } 710 } 711 XGI_SetRegANDOR(XGI_Pr->P3c4,0x21,0x1F,data); 712 713 XGI_New_SetVCLKState(XGI_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex); 714} 715 716/*********************************************/ 717/* LOAD DAC */ 718/*********************************************/ 719 720extern const uint8_t XGI_MDA_DAC[]; 721extern const uint8_t XGI_CGA_DAC[]; 722extern const uint8_t XGI_EGA_DAC[]; 723extern const uint8_t XGI_VGA_DAC[]; 724 725void 726XGI_New_LoadDAC(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 727 USHORT ModeNo, USHORT ModeIdIndex) 728{ 729 USHORT data,data2; 730 USHORT time,i,j,k,m,n,o; 731 USHORT si,di,bx,dl,al,ah,dh; 732 USHORT shiftflag; 733 XGIIOADDRESS DACAddr, DACData; 734 const uint8_t *table = NULL; 735 736 if(ModeNo <= 0x13) { 737 data = XGI_Pr->SModeIDTable[ModeIdIndex].St_ModeFlag; 738 } else { 739 data = XGI_Pr->EModeIDTable[ModeIdIndex].Ext_ModeFlag; 740 } 741 742 data &= DACInfoFlag; 743 time = 64; 744 if(data == 0x00) table = XGI_MDA_DAC; 745 if(data == 0x08) table = XGI_CGA_DAC; 746 if(data == 0x10) table = XGI_EGA_DAC; 747 if(data == 0x18) { 748 time = 256; 749 table = XGI_VGA_DAC; 750 } 751 if(time == 256) j = 16; 752 else j = time; 753 754 if( ( (XGI_Pr->VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */ 755 (XGI_Pr->VBType & VB_NoLCD) ) || 756 (XGI_Pr->VBInfo & SetCRT2ToLCDA) || /* LCDA */ 757 (!(XGI_Pr->SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */ 758 DACAddr = XGI_Pr->P3c8; 759 DACData = XGI_Pr->P3c9; 760 shiftflag = 0; 761 XGI_SetRegByte(XGI_Pr->P3c6,0xFF); 762 } else { 763 shiftflag = 1; 764 DACAddr = XGI_Pr->Part5Port; 765 DACData = XGI_Pr->Part5Port + 1; 766 } 767 768 XGI_SetRegByte(DACAddr,0x00); 769 770 for(i=0; i<j; i++) { 771 data = table[i]; 772 for(k=0; k<3; k++) { 773 data2 = 0; 774 if(data & 0x01) data2 = 0x2A; 775 if(data & 0x02) data2 += 0x15; 776 if(shiftflag) data2 <<= 2; 777 XGI_SetRegByte(DACData, data2); 778 data >>= 2; 779 } 780 } 781 782 if(time == 256) { 783 for(i = 16; i < 32; i++) { 784 data = table[i]; 785 if(shiftflag) data <<= 2; 786 for(k = 0; k < 3; k++) XGI_SetRegByte(DACData, data); 787 } 788 si = 32; 789 for(m = 0; m < 9; m++) { 790 di = si; 791 bx = si + 4; 792 dl = 0; 793 for(n = 0; n < 3; n++) { 794 for(o = 0; o < 5; o++) { 795 dh = table[si]; 796 ah = table[di]; 797 al = table[bx]; 798 si++; 799 XGI_WriteDAC(DACData, shiftflag, dl, ah, al, dh); 800 } 801 si -= 2; 802 for(o = 0; o < 3; o++) { 803 dh = table[bx]; 804 ah = table[di]; 805 al = table[si]; 806 si--; 807 XGI_WriteDAC(DACData, shiftflag, dl, ah, al, dh); 808 } 809 dl++; 810 } /* for n < 3 */ 811 si += 5; 812 } /* for m < 9 */ 813 } 814} 815 816/*********************************************/ 817/* SET CRT1 REGISTER GROUP */ 818/*********************************************/ 819 820static void 821XGI_New_SetCRT1Group(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 822 USHORT ModeNo, USHORT ModeIdIndex) 823{ 824 const USHORT StandTableIndex = XGI_GetModePtr(XGI_Pr->SModeIDTable, 825 XGI_Pr->ModeType, 826 ModeNo, ModeIdIndex); 827 USHORT RefreshRateTableIndex = 0; 828 829 830/* 831 if(XGI_Pr->SetFlag & LowModeTests) { 832 if(XGI_Pr->VBInfo & (SetSimuScanMode | SwitchToCRT2)) { 833 XGI_New_DisableBridge(XGI_Pr, HwInfo); 834 } 835 } 836*/ 837 XGI_SetSeqRegs(StandTableIndex, XGI_Pr); 838 XGI_SetMiscRegs(StandTableIndex, XGI_Pr); 839 XGI_SetCRTCRegs(StandTableIndex, XGI_Pr); 840 XGI_SetATTRegs(ModeNo, StandTableIndex, ModeIdIndex, XGI_Pr); 841 XGI_SetGRCRegs(StandTableIndex, XGI_Pr); 842 XGI_ClearExt1Regs(ModeNo, XGI_Pr); 843 XGI_ResetCRT1VCLK(XGI_Pr, HwInfo); 844 845 XGI_Pr->SetFlag &= (~ProgrammingCRT2); 846 847#ifdef LINUX_XF86 848 xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n", 849 XGI_Pr->VBType, XGI_Pr->VBInfo); 850#endif 851 852 if(XGI_Pr->VBInfo & SetSimuScanMode) { 853 if(XGI_Pr->VBInfo & SetInSlaveMode) { 854 XGI_Pr->SetFlag |= ProgrammingCRT2; 855 } 856 } 857 858 if(XGI_Pr->VBInfo & SetCRT2ToLCDA) { 859 XGI_Pr->SetFlag |= ProgrammingCRT2; 860 } 861 862 if(!(XGI_Pr->VBInfo & SetCRT2ToLCDA)) { 863 XGI_Pr->SetFlag &= ~ProgrammingCRT2; 864 } 865 866 if(RefreshRateTableIndex != 0xFFFF) { 867 XGI_SetSync(RefreshRateTableIndex, XGI_Pr); 868 XGI_New_SetCRT1CRTC(XGI_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); 869 XGI_New_SetCRT1Offset(XGI_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); 870 XGI_New_SetCRT1VCLK(XGI_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); 871 } 872 873 XGI_New_SetCRT1ModeRegs(XGI_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex); 874 875 XGI_New_LoadDAC(XGI_Pr, HwInfo, ModeNo, ModeIdIndex); 876} 877 878 879/*********************************************/ 880/* XFree86: SET SCREEN PITCH */ 881/*********************************************/ 882 883#ifdef LINUX_XF86 884static void 885XGI_SetPitchCRT1(VB_DEVICE_INFO *XGI_Pr, ScrnInfoPtr pScrn) 886{ 887 XGIPtr pXGI = XGIPTR(pScrn); 888 UShort HDisplay = pXGI->scrnPitch >> 3; 889 890 XGI_SetReg(XGI_Pr->P3d4,0x13,(HDisplay & 0xFF)); 891 XGI_SetRegANDOR(XGI_Pr->P3c4,0x0E,0xF0,(HDisplay>>8)); 892} 893#endif 894 895/*********************************************/ 896/* XFree86: XGIBIOSSetMode() */ 897/* for non-Dual-Head mode */ 898/*********************************************/ 899 900#ifdef LINUX_XF86 901BOOLEAN 902XGIBIOSSetMode(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 903 ScrnInfoPtr pScrn, DisplayModePtr mode) 904{ 905 XGIPtr pXGI = XGIPTR(pScrn); 906 UShort ModeNo=0; 907 BOOLEAN SetModeRet = FALSE ; 908 UShort HDisplay = pXGI->scrnOffset >> 3 ; 909 910#if XGI_USING_BIOS_SETMODE 911 PDEBUG(ErrorF("XGI_USING_BIOS_SETMODE \n")); 912 if ((pXGI->pVbe != NULL) && (pXGI->pVbe->pInt10 != NULL)) { 913 xf86Int10InfoPtr pInt = pXGI->pVbe->pInt10; 914 915 if (xf86LoadSubModule(pScrn, "int10")) { 916 pInt->num = 0x10; 917 pInt->ax = 0x80 | ModeNo; 918 919 /* ah = 0, set mode */ 920 xf86ExecX86int10(pInt); 921 SetModeRet = ((pInt->ax & 0x7f) == ModeNo); 922 } 923 } 924 else 925#endif 926 { 927 PDEBUG(ErrorF("XGI_USING_C_code_SETMODE \n")); 928 /* Jong 08/21/2007; support external modeline in X configuration file */ 929 /* ------------------------------------------------------------------ */ 930 HwInfo->BPP = pScrn->bitsPerPixel; 931 HwInfo->Frequency = mode->VRefresh; 932 HwInfo->Horizontal_ACTIVE = mode->HDisplay; 933 HwInfo->Vertical_ACTIVE = mode->VDisplay; 934 HwInfo->Interlace=FALSE; 935 936 if( (mode->type == M_T_USERDEF) || ((mode->type & M_T_CLOCK_CRTC_C) == M_T_CLOCK_CRTC_C) ) /* custom mode */ 937 { 938 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting a customer mode %dx%d\n", mode->HDisplay, mode->VDisplay); 939 940 HwInfo->SpecifyTiming = TRUE; 941 HwInfo->Horizontal_FP = mode->HSyncStart - mode->HDisplay; /* HSyncStart - HDisplay */ 942 HwInfo->Horizontal_BP = mode->HTotal - mode->HSyncEnd; /* HTotal - HSyncEnd */ 943 HwInfo->Horizontal_SYNC = mode->HSyncEnd - mode->HSyncStart; /* HSyncEnd - HSyncStart */ 944 HwInfo->Vertical_FP = mode->VSyncStart - mode->VDisplay; 945 HwInfo->Vertical_BP = mode->VTotal - mode->VSyncEnd; 946 HwInfo->Vertical_SYNC = mode->VSyncEnd - mode->VSyncStart; 947 HwInfo->DCLK = mode->Clock; 948 } 949 else 950 { 951 HwInfo->SpecifyTiming = FALSE; 952 953 ModeNo = XGI_CalcModeIndex(pScrn, mode, pXGI->VBFlags); 954 if(!ModeNo) return FALSE; 955 956 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting a standard mode 0x%x\n", ModeNo); 957 } 958 /* ------------------------------------------------------------------ */ 959 960 SetModeRet = XGISetModeNew(HwInfo, XGI_Pr, ModeNo); 961 PDEBUG(ErrorF("out_of_C_code_SETMODE \n")); 962 } 963 964 965 /* SetPitch: Adapt to virtual size & position */ 966 if ((ModeNo > 0x13) || (mode->type == M_T_USERDEF) || ((mode->type & M_T_CLOCK_CRTC_C) == M_T_CLOCK_CRTC_C)) { 967 XGI_SetReg(XGI_Pr->Part1Port, 0x2f, 1); //yilin for crt2pitch it shoude modify if not colone mode 968 XGI_SetReg(XGI_Pr->Part1Port, 0x07, (HDisplay & 0xFF)); 969 XGI_SetRegANDOR(XGI_Pr->Part1Port, 0x09, 0xF0, (HDisplay>>8)); 970 971 /* Jong10052009; Set pitch with HDisplay = pXGI->scrnOffset >> 3 */ 972 PDEBUG(ErrorF("scrnOffset is %d...\n", pXGI->scrnOffset)); 973 XGI_SetReg(XGI_Pr->P3d4,0x13,(HDisplay & 0xFF)); 974 XGI_SetRegANDOR(XGI_Pr->P3c4,0x0E,0xF0,(HDisplay>>8)); 975 /* 976 XGI_SetReg(XGI_Pr->P3d4,0x13,(HDisplay & 0xFF)); 977 XGI_SetRegANDOR(XGI_Pr->P3c4,0x0E,0xF0,(HDisplay>>8)); */ 978 } 979 980 return SetModeRet; 981} 982 983/*********************************************/ 984/* XFree86: XGIBIOSSetModeCRT1() */ 985/* for Dual-Head modes */ 986/*********************************************/ 987 988BOOLEAN 989XGIBIOSSetModeCRT1(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwInfo, 990 ScrnInfoPtr pScrn, DisplayModePtr mode) 991{ 992 XGIPtr pXGI = XGIPTR(pScrn); 993 USHORT ModeIdIndex, ModeNo=0; 994 UCHAR backupreg=0; 995 unsigned vga_info; 996 XGIEntPtr pXGIEnt = ENTITY_PRIVATE(pXGI); 997 UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0; 998 999 1000 ModeNo = XGI_CalcModeIndex(pScrn, mode, pXGI->VBFlags); 1001 if(!ModeNo) return FALSE; 1002 1003 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1004 "Setting standard mode 0x%x on CRT1\n", ModeNo); 1005 1006#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__)) 1007 vga_info = XGI_GetSetBIOSScratch(pScrn, 0x489, 0xff); 1008#else 1009 vga_info = 0x11; 1010#endif 1011 XGIInitPCIetc(XGI_Pr, HwInfo); 1012 1013 XGI_SetReg(XGI_Pr->P3c4,0x05,0x86); 1014 1015 if (!XGI_SearchModeID(XGI_Pr->SModeIDTable, XGI_Pr->EModeIDTable, 1016 vga_info, &ModeNo, &ModeIdIndex)) { 1017 return FALSE; 1018 } 1019 1020 /* Determine VBType */ 1021 XGI_New_GetVBType(XGI_Pr, HwInfo); 1022 1023 if (XGI_Pr->VBType & VB_XGI301BLV302BLV) { 1024 backupreg = XGI_GetReg(XGI_Pr->P3d4,0x38); 1025 } 1026 1027 /* Get VB information (connectors, connected devices) */ 1028 /* (We don't care if the current mode is a CRT2 mode) */ 1029 XGI_SetLowModeTest(XGI_Pr, ModeNo, HwInfo); 1030 1031 /* Set mode on CRT1 */ 1032 XGI_New_SetCRT1Group(XGI_Pr, HwInfo, ModeNo, ModeIdIndex); 1033 /* SetPitch: Adapt to virtual size & position */ 1034 XGI_SetPitchCRT1(XGI_Pr, pScrn); 1035 1036 1037 /* Reset CRT2 if changing mode on CRT1 */ 1038 if(IS_DUAL_HEAD(pXGI)) { 1039 if(pXGIEnt->CRT2ModeNo != -1) { 1040 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1041 "(Re-)Setting mode for CRT2\n"); 1042 backupcr30 = XGI_GetReg(XGI_Pr->P3d4,0x30); 1043 backupcr31 = XGI_GetReg(XGI_Pr->P3d4,0x31); 1044 backupcr35 = XGI_GetReg(XGI_Pr->P3d4,0x35); 1045 backupcr38 = XGI_GetReg(XGI_Pr->P3d4,0x38); 1046 if(XGI_Pr->VBType & VB_XGIVB) { 1047 /* Backup LUT-enable */ 1048 if(pXGIEnt->CRT2ModeSet) { 1049 backupp40d = XGI_GetReg(XGI_Pr->Part4Port,0x0d) & 0x08; 1050 } 1051 } 1052 if(XGI_Pr->VBInfo & SetCRT2ToLCDA) { 1053 XGI_SetReg(XGI_Pr->P3d4,0x30,pXGIEnt->CRT2CR30); 1054 XGI_SetReg(XGI_Pr->P3d4,0x31,pXGIEnt->CRT2CR31); 1055 XGI_SetReg(XGI_Pr->P3d4,0x35,pXGIEnt->CRT2CR35); 1056 XGI_SetReg(XGI_Pr->P3d4,0x38,pXGIEnt->CRT2CR38); 1057 } 1058 1059 XGI_SetReg(XGI_Pr->P3d4,0x30,backupcr30); 1060 XGI_SetReg(XGI_Pr->P3d4,0x31,backupcr31); 1061 XGI_SetReg(XGI_Pr->P3d4,0x35,backupcr35); 1062 XGI_SetReg(XGI_Pr->P3d4,0x38,backupcr38); 1063 if(XGI_Pr->VBType & VB_XGIVB) { 1064 XGI_SetRegANDOR(XGI_Pr->Part4Port,0x0d, ~0x08, backupp40d); 1065 } 1066 } 1067 } 1068 1069 /* Warning: From here, the custom mode entries in XGI_Pr are 1070 * possibly overwritten 1071 */ 1072 1073 XGI_HandleCRT1(XGI_Pr); 1074 1075 XGI_New_DisplayOn(XGI_Pr); 1076 XGI_SetRegByte(XGI_Pr->P3c6,0xFF); 1077 1078 /* Backup/Set ModeNo in BIOS scratch area */ 1079 XGI_GetSetModeID(pScrn,ModeNo); 1080 1081 return TRUE; 1082} 1083#endif /* Linux_XF86 */ 1084