1/* 2 * DAC helper functions (Save/Restore, MemClk, etc) 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * 30 * -------------------------------------------------------------------------- 31 * 32 * SiS_compute_vclk(), SiSCalcClock() and parts of SiSMclk(): 33 * 34 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England 35 * Written by: 36 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 37 * Mike Chapman <mike@paranoia.com>, 38 * Juanjo Santamarta <santamarta@ctv.es>, 39 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 40 * David Thomas <davtom@dream.org.uk>, 41 * Thomas Winischhofer <thomas@winischhofer.net>. 42 * 43 * Licensed under the following terms: 44 * 45 * Permission to use, copy, modify, distribute, and sell this software and its 46 * documentation for any purpose is hereby granted without fee, provided that 47 * the above copyright notice appears in all copies and that both that copyright 48 * notice and this permission notice appear in supporting documentation, and 49 * and that the name of the copyright holder not be used in advertising 50 * or publicity pertaining to distribution of the software without specific, 51 * written prior permission. The copyright holder makes no representations 52 * about the suitability of this software for any purpose. It is provided 53 * "as is" without expressed or implied warranty. 54 * 55 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 56 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 57 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR 58 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 59 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 60 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 61 * PERFORMANCE OF THIS SOFTWARE. 62 */ 63 64#ifdef HAVE_CONFIG_H 65#include "config.h" 66#endif 67 68#include "sis.h" 69#define SIS_NEED_inSISREG 70#define SIS_NEED_inSISREGW 71#define SIS_NEED_inSISREGL 72#define SIS_NEED_outSISREG 73#define SIS_NEED_outSISREGW 74#define SIS_NEED_outSISREGL 75#define SIS_NEED_inSISIDXREG 76#define SIS_NEED_outSISIDXREG 77#define SIS_NEED_orSISIDXREG 78#define SIS_NEED_andSISIDXREG 79#define SIS_NEED_MYMMIO 80#include "sis_regs.h" 81#include "sis_dac.h" 82 83static void SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); 84static void SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 85static void SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); 86static void SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 87static void SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); 88static void SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 89static void SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); 90static void SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); 91static void SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); 92static void SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 93static void SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 94static void SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); 95static void SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors, 96 int *indicies, LOCO *colors, int myshift); 97static void SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr); 98 99UChar SiSGetCopyROP(int rop); 100UChar SiSGetPatternROP(int rop); 101 102static const UShort ch700xidx[] = { 103 0x00,0x07,0x08,0x0a,0x0b,0x04,0x09,0x20,0x21,0x18,0x19,0x1a, 104 0x1b,0x1c,0x1d,0x1e,0x1f, /* 0x0e, - Don't save the power register */ 105 0x01,0x03,0x06,0x0d,0x11,0x13,0x14,0x15,0x17,0x22,0x23,0x24 106 }; 107 108static const UShort ch701xidx[] = { 109 0x1c,0x5f,0x64,0x6f,0x70,0x71,0x72,0x73,0x74,0x76,0x78,0x7d, 110 0x67,0x68,0x69,0x6a,0x6b,0x1e,0x00,0x01,0x02,0x04,0x03,0x05, 111 0x06,0x07,0x08,0x15,0x1f,0x0c,0x0d,0x0e,0x0f,0x10,0x66 112 }; 113 114int SiS_compute_vclk( 115 int Clock, 116 int *out_n, 117 int *out_dn, 118 int *out_div, 119 int *out_sbit, 120 int *out_scale) 121{ 122 float f,x,y,t, error, min_error; 123 int n, dn, best_n=0, best_dn=0; 124 125 /* 126 * Rules 127 * 128 * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator) 129 * Factor = (Divider/Post Scalar) 130 * Divider is 1 or 2 131 * Post Scalar is 1, 2, 3, 4, 6 or 8 132 * Numberator ranged from 1 to 128 133 * DeNumerator ranged from 1 to 32 134 * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz 135 * b. Post Scalar selected from 1, 2, 4 or 8 first. 136 * c. DeNumerator selected from 2. 137 * 138 * According to rule a and b, the VCO ranges that can be scaled by 139 * rule b are: 140 * 150 - 250 (Factor = 1) 141 * 75 - 125 (Factor = 2) 142 * 37.5 - 62.5 (Factor = 4) 143 * 18.75 - 31.25 (Factor = 8) 144 * 145 * The following ranges use Post Scalar 3 or 6: 146 * 125 - 150 (Factor = 1.5) 147 * 62.5 - 75 (Factor = 3) 148 * 31.25 - 37.5 (Factor = 6) 149 * 150 * Steps: 151 * 1. divide the Clock by 2 until the Clock is less or equal to 31.25. 152 * 2. if the divided Clock is range from 18.25 to 31.25, than 153 * the Factor is 1, 2, 4 or 8. 154 * 3. if the divided Clock is range from 15.625 to 18.25, than 155 * the Factor is 1.5, 3 or 6. 156 * 4. select the Numberator and DeNumberator with minimum deviation. 157 * 158 * ** this function can select VCLK ranged from 18.75 to 250 Mhz 159 */ 160 161 f = (float) Clock; 162 f /= 1000.0; 163 if((f > 250.0) || (f < 18.75)) 164 return 0; 165 166 min_error = f; 167 y = 1.0; 168 x = f; 169 while(x > 31.25) { 170 y *= 2.0; 171 x /= 2.0; 172 } 173 if(x >= 18.25) { 174 x *= 8.0; 175 y = 8.0 / y; 176 } else if(x >= 15.625) { 177 x *= 12.0; 178 y = 12.0 / y; 179 } 180 181 t = y; 182 if(t == (float) 1.5) { 183 *out_div = 2; 184 t *= 2.0; 185 } else { 186 *out_div = 1; 187 } 188 if(t > (float) 4.0) { 189 *out_sbit = 1; 190 t /= 2.0; 191 } else { 192 *out_sbit = 0; 193 } 194 195 *out_scale = (int) t; 196 197 for(dn = 2; dn <= 32; dn++) { 198 for(n = 1; n <= 128; n++) { 199 error = x; 200 error -= ((float) 14.318 * (float) n / (float) dn); 201 if(error < (float) 0) 202 error = -error; 203 if(error < min_error) { 204 min_error = error; 205 best_n = n; 206 best_dn = dn; 207 } 208 } 209 } 210 *out_n = best_n; 211 *out_dn = best_dn; 212 PDEBUG(ErrorF("SiS_compute_vclk: Clock=%d, n=%d, dn=%d, div=%d, sbit=%d," 213 " scale=%d\n", Clock, best_n, best_dn, *out_div, 214 *out_sbit, *out_scale)); 215 return 1; 216} 217 218void 219SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk) 220{ 221 SISPtr pSiS = SISPTR(pScrn); 222 int M, N, P , PSN, VLD , PSNx ; 223 int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; 224 double abest = 42.0; 225 double target; 226 double Fvco, Fout; 227 double error, aerror; 228 229 /* 230 * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) 231 * 232 * M = Numerator [1:128] 233 * N = DeNumerator [1:32] 234 * VLD = Divider (Vco Loop Divider) : divide by 1, 2 235 * P = Post Scaler : divide by 1, 2, 3, 4 236 * PSN = Pre Scaler (Reference Divisor Select) 237 * 238 * result in vclk[] 239 */ 240#define Midx 0 241#define Nidx 1 242#define VLDidx 2 243#define Pidx 3 244#define PSNidx 4 245#define Fref 14318180 246/* stability constraints for internal VCO -- MAX_VCO also determines 247 * the maximum Video pixel clock */ 248#define MIN_VCO Fref 249#define MAX_VCO 135000000 250#define MAX_VCO_5597 353000000 251#define MAX_PSN 0 /* no pre scaler for this chip */ 252#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ 253 254 int M_min = 2; 255 int M_max = 128; 256 257 target = clock * 1000; 258 259 if(pSiS->Chipset == PCI_CHIP_SIS5597 || pSiS->Chipset == PCI_CHIP_SIS6326) { 260 261 int low_N = 2; 262 int high_N = 5; 263 264 PSN = 1; 265 P = 1; 266 if(target < MAX_VCO_5597 / 2) P = 2; 267 if(target < MAX_VCO_5597 / 3) P = 3; 268 if(target < MAX_VCO_5597 / 4) P = 4; 269 if(target < MAX_VCO_5597 / 6) P = 6; 270 if(target < MAX_VCO_5597 / 8) P = 8; 271 272 Fvco = P * target; 273 274 for(N = low_N; N <= high_N; N++) { 275 276 double M_desired = Fvco / Fref * N; 277 if(M_desired > M_max * max_VLD) continue; 278 279 if(M_desired > M_max) { 280 M = M_desired / 2 + 0.5; 281 VLD = 2; 282 } else { 283 M = Fvco / Fref * N + 0.5; 284 VLD = 1; 285 } 286 287 Fout = (double)Fref * (M * VLD)/(N * P); 288 289 error = (target - Fout) / target; 290 aerror = (error < 0) ? -error : error; 291 if(aerror < abest) { 292 abest = aerror; 293 bestM = M; 294 bestN = N; 295 bestP = P; 296 bestPSN = PSN; 297 bestVLD = VLD; 298 } 299 } 300 301 } else { 302 303 for(PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { 304 305 int low_N, high_N; 306 double FrefVLDPSN; 307 308 PSN = !PSNx ? 1 : 4; 309 310 low_N = 2; 311 high_N = 32; 312 313 for(VLD = 1 ; VLD <= max_VLD ; VLD++) { 314 315 FrefVLDPSN = (double)Fref * VLD / PSN; 316 317 for(N = low_N; N <= high_N; N++) { 318 double tmp = FrefVLDPSN / N; 319 320 for(P = 1; P <= 4; P++) { 321 double Fvco_desired = target * ( P ); 322 double M_desired = Fvco_desired / tmp; 323 324 /* Which way will M_desired be rounded? 325 * Do all three just to be safe. 326 */ 327 int M_low = M_desired - 1; 328 int M_hi = M_desired + 1; 329 330 if(M_hi < M_min || M_low > M_max) continue; 331 332 if(M_low < M_min) M_low = M_min; 333 334 if(M_hi > M_max) M_hi = M_max; 335 336 for(M = M_low; M <= M_hi; M++) { 337 Fvco = tmp * M; 338 if(Fvco <= MIN_VCO) continue; 339 if(Fvco > MAX_VCO) break; 340 341 Fout = Fvco / ( P ); 342 343 error = (target - Fout) / target; 344 aerror = (error < 0) ? -error : error; 345 if(aerror < abest) { 346 abest = aerror; 347 bestM = M; 348 bestN = N; 349 bestP = P; 350 bestPSN = PSN; 351 bestVLD = VLD; 352 } 353#ifdef TWDEBUG 354 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 355 "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", 356 (float)(clock / 1000.), M, N, P, VLD, PSN); 357 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 358 "Freq. set: %.2f MHz\n", Fout / 1.0e6); 359#endif 360 } 361 } 362 } 363 } 364 } 365 } 366 367 vclk[Midx] = bestM; 368 vclk[Nidx] = bestN; 369 vclk[VLDidx] = bestVLD; 370 vclk[Pidx] = bestP; 371 vclk[PSNidx] = bestPSN; 372} 373 374static void 375SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) 376{ 377 SISPtr pSiS = SISPTR(pScrn); 378 int i, max; 379 380 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "SiSSave()\n")); 381 382#ifdef UNLOCK_ALWAYS 383 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 384#endif 385 386 switch(pSiS->Chipset) { 387 case PCI_CHIP_SIS5597: 388 max=0x3C; 389 break; 390 case PCI_CHIP_SIS6326: 391 case PCI_CHIP_SIS530: 392 max=0x3F; 393 break; 394 default: 395 max=0x37; 396 } 397 398 /* Save extended SR registers */ 399 for(i = 0x00; i <= max; i++) { 400 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); 401#ifdef TWDEBUG 402 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 403 "SR%02X - %02X \n", i, sisReg->sisRegs3C4[i]); 404#endif 405 } 406 407#ifdef TWDEBUG 408 for(i = 0x00; i <= 0x3f; i++) { 409 inSISIDXREG(SISCR, i, max); 410 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 411 "CR%02X - %02X \n", i, max); 412 } 413#endif 414 415 /* Save lock (will not be restored in SiSRestore()!) */ 416 inSISIDXREG(SISCR, 0x80, sisReg->sisRegs3D4[0x80]); 417 418 sisReg->sisRegs3C2 = inSISREG(SISMISCR); /* Misc */ 419 420 /* Save TV registers */ 421 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 422 outSISIDXREG(SISCR, 0x80, 0x86); 423 for(i = 0x00; i <= 0x44; i++) { 424 sisReg->sis6326tv[i] = SiS6326GetTVReg(pScrn, i); 425#ifdef TWDEBUG 426 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 427 "VR%02X - %02X \n", i,sisReg->sis6326tv[i]); 428#endif 429 } 430 } 431} 432 433static void 434SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 435{ 436 SISPtr pSiS = SISPTR(pScrn); 437 int i, max; 438 UChar tmp; 439 440 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SiSRestore()\n")); 441 442#ifdef UNLOCK_ALWAYS 443 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 444#endif 445 446 switch(pSiS->Chipset) { 447 case PCI_CHIP_SIS5597: 448 max = 0x3C; 449 break; 450 case PCI_CHIP_SIS6326: 451 case PCI_CHIP_SIS530: 452 max = 0x3F; 453 break; 454 default: 455 max = 0x37; 456 } 457 458 /* Disable TV on 6326 before restoring */ 459 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 460 outSISIDXREG(SISCR, 0x80, 0x86); 461 tmp = SiS6326GetTVReg(pScrn, 0x00); 462 tmp &= ~0x04; 463 SiS6326SetTVReg(pScrn, 0x00, tmp); 464 } 465 466 /* Restore other extended SR registers */ 467 for(i = 0x06; i <= max; i++) { 468 if((i == 0x13) || (i == 0x2a) || (i == 0x2b)) continue; 469 outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); 470 } 471 472 /* Now restore VCLK (with correct SR38 setting) */ 473 outSISIDXREG(SISSR, 0x13, sisReg->sisRegs3C4[0x13]); 474 outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]); 475 outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]); 476 477 /* Misc */ 478 outSISREG(SISMISCW, sisReg->sisRegs3C2); 479 480 /* MemClock needs this to take effect */ 481 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 482 usleep(10000); 483 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 484 485 /* Restore TV registers */ 486 pSiS->SiS6326Flags &= ~SIS6326_TVON; 487 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 488 for(i = 0x01; i <= 0x44; i++) { 489 SiS6326SetTVReg(pScrn, i, sisReg->sis6326tv[i]); 490#ifdef TWDEBUG 491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 492 "VR%02x restored to %02x\n", 493 i, sisReg->sis6326tv[i]); 494#endif 495 } 496 tmp = SiS6326GetXXReg(pScrn, 0x13); 497 SiS6326SetXXReg(pScrn, 0x13, 0xfa); 498 tmp = SiS6326GetXXReg(pScrn, 0x14); 499 SiS6326SetXXReg(pScrn, 0x14, 0xc8); 500 if(!(sisReg->sisRegs3C4[0x0D] & 0x04)) { 501 tmp = SiS6326GetXXReg(pScrn, 0x13); 502 SiS6326SetXXReg(pScrn, 0x13, 0xf6); 503 tmp = SiS6326GetXXReg(pScrn, 0x14); 504 SiS6326SetXXReg(pScrn, 0x14, 0xbf); 505 } 506 if(sisReg->sis6326tv[0] & 0x04) pSiS->SiS6326Flags |= SIS6326_TVON; 507 } 508} 509 510/* Save SiS 300 series register contents */ 511static void 512SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) 513{ 514 SISPtr pSiS = SISPTR(pScrn); 515 int i; 516 517 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "SiS300Save()\n")); 518 519#ifdef UNLOCK_ALWAYS 520 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 521#endif 522 523 /* Save SR registers */ 524 for(i = 0x00; i <= 0x3D; i++) { 525 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); 526#ifdef TWDEBUG 527 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 528 "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); 529#endif 530 } 531 532 /* Save CR registers */ 533 for(i = 0x00; i < 0x40; i++) { 534 inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); 535#ifdef TWDEBUG 536 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 537 "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]); 538#endif 539 } 540 541 /* Save Misc register */ 542 sisReg->sisRegs3C2 = inSISREG(SISMISCR); 543 544 /* Save FQBQ and GUI timer settings */ 545 if(pSiS->Chipset == PCI_CHIP_SIS630) { 546 sisReg->sisRegsPCI50 = sis_pci_read_host_bridge_u32(0x50); 547 sisReg->sisRegsPCIA0 = sis_pci_read_host_bridge_u32(0xA0); 548#ifdef TWDEBUG 549 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 550 "PCI Config 50 = %lx\n", sisReg->sisRegsPCI50); 551 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 552 "PCI Config A0 = %lx\n", sisReg->sisRegsPCIA0); 553#endif 554 } 555 556 /* Save panel link/video bridge registers */ 557#ifndef TWDEBUG 558 if(!pSiS->UseVESA) { 559#endif 560 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) 561 SiSLVDSChrontelSave(pScrn, sisReg); 562 else if(pSiS->VBFlags2 & VB2_301) 563 SiS301Save(pScrn, sisReg); 564 else if(pSiS->VBFlags2 & VB2_30xBLV) 565 SiS301BSave(pScrn, sisReg); 566#ifndef TWDEBUG 567 } 568#endif 569 570 /* Save Mode number */ 571 sisReg->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF); 572 573#ifdef TWDEBUG 574 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 575 "BIOS mode ds:449 = 0x%x\n", sisReg->BIOSModeSave); 576#endif 577} 578 579/* Restore SiS300 series register contents */ 580static void 581SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 582{ 583 SISPtr pSiS = SISPTR(pScrn); 584 int i,temp; 585 CARD32 temp1, temp2; 586 587 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SiS300Restore()\n")); 588 589#ifdef UNLOCK_ALWAYS 590 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 591#endif 592 593 /* Wait for accelerator to finish on-going drawing operations. */ 594 inSISIDXREG(SISSR, 0x1E, temp); 595 if(temp & (0x40|0x10|0x02)) { 596 while ( (SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; 597 while ( (SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; 598 while ( (SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; 599 } 600 601 if(!(pSiS->UseVESA)) { 602 if(pSiS->VBFlags2 & VB2_LVDS) { 603 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 604 SiSSetLVDSetc(pSiS->SiS_Pr); 605 SiS_GetVBType(pSiS->SiS_Pr); 606 SiS_UnLockCRT2(pSiS->SiS_Pr); 607 SiS_DisableBridge(pSiS->SiS_Pr); 608 } 609 } 610 611 /* Restore extended CR registers */ 612 for(i = 0x19; i < 0x40; i++) { 613 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); 614 } 615 616 if(pSiS->Chipset != PCI_CHIP_SIS300) { 617 UChar val; 618 inSISIDXREG(SISCR, 0x1A, val); 619 if(val == sisReg->sisRegs3D4[0x19]) 620 outSISIDXREG(SISCR, 0x1A, sisReg->sisRegs3D4[0x19]); 621 inSISIDXREG(SISCR,0x19,val); 622 if(val == sisReg->sisRegs3D4[0x1A]) 623 outSISIDXREG(SISCR, 0x19, sisReg->sisRegs3D4[0x1A]); 624 } 625 626 /* Set (and leave) PCI_IO_ENABLE on if accelerators are on */ 627 if(sisReg->sisRegs3C4[0x1e] & 0x50) { 628 sisReg->sisRegs3C4[0x20] |= 0x20; 629 outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]); 630 } 631 632 /* If TQ is switched on, don't switch it off ever again! 633 * Therefore, always restore registers with TQ enabled. 634 */ 635 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 636 temp = (pScrn->videoRam/64) - 8; 637 sisReg->sisRegs3C4[0x26] = temp & 0xFF; 638 sisReg->sisRegs3C4[0x27] = ((temp >> 8) & 3) | 0xF0; 639 } 640 641 /* Restore extended SR registers */ 642 for(i = 0x06; i <= 0x3D; i++) { 643 temp = sisReg->sisRegs3C4[i]; 644 if(!(pSiS->UseVESA)) { 645 if(pSiS->VBFlags2 & VB2_LVDS) { 646 if(i == 0x11) { 647 inSISIDXREG(SISSR,0x11,temp); 648 temp &= 0x0c; 649 temp |= (sisReg->sisRegs3C4[i] & 0xf3); 650 } 651 } 652 } 653 outSISIDXREG(SISSR, i, temp); 654 } 655 656 /* Restore VCLK and ECLK */ 657 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xB)) { 658 outSISIDXREG(SISSR,0x31,0x20); 659 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 660 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 661 outSISIDXREG(SISSR,0x2d,0x80); 662 outSISIDXREG(SISSR,0x31,0x10); 663 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 664 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 665 outSISIDXREG(SISSR,0x2d,0x80); 666 } 667 outSISIDXREG(SISSR,0x31,0x00); 668 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 669 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 670 outSISIDXREG(SISSR,0x2d,0x80); 671 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xB)) { 672 outSISIDXREG(SISSR,0x31,0x20); 673 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 674 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 675 outSISIDXREG(SISSR,0x31,0x10); 676 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 677 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 678 outSISIDXREG(SISSR,0x31,0x00); 679 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 680 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 681 } 682 683 /* Restore Misc register */ 684 outSISREG(SISMISCW, sisReg->sisRegs3C2); 685 686 /* Restore FQBQ and GUI timer settings */ 687 if(pSiS->Chipset == PCI_CHIP_SIS630) { 688 temp1 = sis_pci_read_host_bridge_u32(0x50); 689 temp2 = sis_pci_read_host_bridge_u32(0xA0); 690 if(sis_pci_read_host_bridge_u32(0x00) == 0x06301039) { 691 temp1 &= 0xf0ffffff; 692 temp1 |= (sisReg->sisRegsPCI50 & ~0xf0ffffff); 693 temp2 &= 0xf0ffffff; 694 temp2 |= (sisReg->sisRegsPCIA0 & ~0xf0ffffff); 695 } else { /* 730 */ 696 temp1 &= 0xfffff9ff; 697 temp1 |= (sisReg->sisRegsPCI50 & ~0xfffff9ff); 698 temp2 &= 0x00ffffff; 699 temp2 |= (sisReg->sisRegsPCIA0 & ~0x00ffffff); 700 } 701 sis_pci_write_host_bridge_u32(0x50, temp1); 702 sis_pci_write_host_bridge_u32(0xA0, temp2); 703 } 704 705 /* Restore panel link/video bridge registers */ 706 if(!(pSiS->UseVESA)) { 707 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) 708 SiSLVDSChrontelRestore(pScrn, sisReg); 709 else if(pSiS->VBFlags2 & VB2_301) 710 SiS301Restore(pScrn, sisReg); 711 else if(pSiS->VBFlags2 & VB2_30xBLV) 712 SiS301BRestore(pScrn, sisReg); 713 } 714 715 /* MemClock needs this to take effect */ 716 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 717 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 718 719 /* Restore mode number */ 720 SiS_GetSetModeID(pScrn,sisReg->BIOSModeSave); 721} 722 723/* Save SiS315 series register contents */ 724static void 725SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) 726{ 727 SISPtr pSiS = SISPTR(pScrn); 728 int i, max; 729 730 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "SiS315Save()\n")); 731 732#ifdef UNLOCK_ALWAYS 733 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 734#endif 735 736 /* Save SR registers */ 737 for(i = 0x00; i <= 0x60; i++) { 738 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); 739#ifdef TWDEBUG 740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 741 "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); 742#endif 743 } 744 745 /* Save command queue location */ 746 sisReg->sisMMIO85C0 = SIS_MMIO_IN32(pSiS->IOBase, 0x85C0); 747 748 /* Save CR registers */ 749 max = 0x7c; 750 if(pSiS->ChipType >= XGI_20) max = 0xff; 751 for(i = 0x00; i <= max; i++) { 752 inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); 753#ifdef TWDEBUG 754 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 755 "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]); 756#endif 757 } 758 759 /* Save video capture registers */ 760 for(i = 0x00; i <= 0x4f; i++) { 761 inSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 762#ifdef TWDEBUG_VID 763 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 764 "Capt%02X Contents - %02X \n", i,sisReg->sisCapt[i]); 765#endif 766 } 767 768 /* Save video playback registers */ 769 for(i = 0x00; i <= 0x3f; i++) { 770 inSISIDXREG(SISVID, i, sisReg->sisVid[i]); 771#ifdef TWDEBUG_VID 772 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 773 "Vid%02X Contents - %02X \n", i,sisReg->sisVid[i]); 774#endif 775 } 776 777 /* Save Misc register */ 778 sisReg->sisRegs3C2 = inSISREG(SISMISCR); 779 780 /* Save panel link/video bridge registers */ 781#ifndef TWDEBUG 782 if(!pSiS->UseVESA) { 783#endif 784 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) 785 SiSLVDSChrontelSave(pScrn, sisReg); 786 else if(pSiS->VBFlags2 & VB2_301) 787 SiS301Save(pScrn, sisReg); 788 else if(pSiS->VBFlags2 & VB2_30xBLV) 789 SiS301BSave(pScrn, sisReg); 790#ifndef TWDEBUG 791 } 792#endif 793 794 /* Save mode number */ 795 sisReg->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF); 796 797#ifdef TWDEBUG 798 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 799 "BIOS mode ds:449 = 0x%x\n", sisReg->BIOSModeSave); 800#endif 801} 802 803/* Restore SiS315/330 series register contents */ 804static void 805SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 806{ 807 SISPtr pSiS = SISPTR(pScrn); 808 int i,temp; 809 810 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SiS315Restore()\n")); 811 812#ifdef UNLOCK_ALWAYS 813 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 814#endif 815 816 /* Wait for accelerator to finish on-going drawing operations. */ 817 inSISIDXREG(SISSR, 0x1E, temp); 818 if(temp & (0x40|0x10|0x02)) { /* 0x40 = 2D, 0x02 = 3D enabled*/ 819 while ( (SIS_MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; 820 while ( (SIS_MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; 821 while ( (SIS_MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; 822 } 823 824 /* We reset the command queue before restoring. 825 * This might be required because we never know what 826 * console driver (like the kernel framebuffer driver) 827 * or application is running and which queue mode it 828 * uses. 829 */ 830 andSISIDXREG(SISCR, 0x55, 0x33); 831 orSISIDXREG(SISSR, 0x26, 0x01); 832 outSISIDXREG(SISSR, 0x27, 0x1F); 833 834 /* Restore extended CR registers */ 835 for(i = 0x19; i < 0x5C; i++) { 836 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); 837 } 838 if(pSiS->ChipType < SIS_661) { 839 outSISIDXREG(SISCR, 0x79, sisReg->sisRegs3D4[0x79]); 840 } 841 outSISIDXREG(SISCR, pSiS->myCR63, sisReg->sisRegs3D4[pSiS->myCR63]); 842 843 /* Leave PCI_IO_ENABLE on if accelerators are on (Is this required?) */ 844 if(sisReg->sisRegs3C4[0x1e] & 0x52) { /* 0x40=2D, 0x02=3D */ 845 sisReg->sisRegs3C4[0x20] |= 0x20; 846 outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]); 847 } 848 849 if(pSiS->SiS_Pr->SiS_SensibleSR11) { 850 sisReg->sisRegs3C4[0x11] &= 0x0f; 851 } 852 853 /* Restore extended SR registers */ 854 for(i = 0x06; i <= 0x3F; i++) { 855 if(i == 0x26) { 856 continue; 857 } else if(i == 0x27) { 858 outSISIDXREG(SISSR, 0x27, sisReg->sisRegs3C4[0x27]); 859 outSISIDXREG(SISSR, 0x26, sisReg->sisRegs3C4[0x26]); 860 } else { 861 outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); 862 } 863 } 864 865 /* Restore VCLK and ECLK */ 866 andSISIDXREG(SISSR,0x31,0xcf); 867 if(pSiS->VBFlags2 & VB2_LVDS) { 868 orSISIDXREG(SISSR,0x31,0x20); 869 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 870 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 871 outSISIDXREG(SISSR,0x2d,0x80); 872 andSISIDXREG(SISSR,0x31,0xcf); 873 orSISIDXREG(SISSR,0x31,0x10); 874 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 875 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 876 outSISIDXREG(SISSR,0x2d,0x80); 877 andSISIDXREG(SISSR,0x31,0xcf); 878 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 879 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 880 outSISIDXREG(SISSR,0x2d,0x01); 881 outSISIDXREG(SISSR,0x31,0x20); 882 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 883 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 884 outSISIDXREG(SISSR,0x31,0x10); 885 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 886 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 887 outSISIDXREG(SISSR,0x31,0x00); 888 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); 889 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); 890 } else { 891 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); 892 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); 893 outSISIDXREG(SISSR,0x2d,0x01); 894 } 895 896#ifndef SISVRAMQ 897 /* Initialize read/write pointer for command queue */ 898 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, SIS_MMIO_IN32(pSiS->IOBase, 0x85C8)); 899#endif 900 /* Restore queue location */ 901 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 902 903 /* Restore Misc register */ 904 outSISREG(SISMISCW, sisReg->sisRegs3C2); 905 906 /* Restore panel link/video bridge registers */ 907 if(!(pSiS->UseVESA)) { 908 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) 909 SiSLVDSChrontelRestore(pScrn, sisReg); 910 else if(pSiS->VBFlags2 & VB2_301) 911 SiS301Restore(pScrn, sisReg); 912 else if(pSiS->VBFlags2 & VB2_30xBLV) 913 SiS301BRestore(pScrn, sisReg); 914 } 915 916 /* MemClock needs this to take effect */ 917 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 918 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 919 920 /* Restore Mode number */ 921 SiS_GetSetModeID(pScrn,sisReg->BIOSModeSave); 922} 923 924static void 925SiSVBSave(ScrnInfoPtr pScrn, SISRegPtr sisReg, int p1, int p2, int p3, int p4) 926{ 927 SISPtr pSiS = SISPTR(pScrn); 928 int i; 929 930 for(i=0; i<=p1; i++) { 931 inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]); 932#ifdef TWDEBUG 933 xf86DrvMsg(0, X_INFO, "301xSave: Part1 0x%02x = 0x%02x\n", i, sisReg->VBPart1[i]); 934#endif 935 } 936 for(i=0; i<=p2; i++) { 937 inSISIDXREG(SISPART2, i, sisReg->VBPart2[i]); 938#ifdef TWDEBUG 939 xf86DrvMsg(0, X_INFO, "301xSave: Part2 0x%02x = 0x%02x\n", i, sisReg->VBPart2[i]); 940#endif 941 } 942 for(i=0; i<=p3; i++) { 943 inSISIDXREG(SISPART3, i, sisReg->VBPart3[i]); 944#ifdef TWDEBUG 945 xf86DrvMsg(0, X_INFO, "301xSave: Part3 0x%02x = 0x%02x\n", i, sisReg->VBPart3[i]); 946#endif 947 } 948 for(i=0; i<=p4; i++) { 949 inSISIDXREG(SISPART4, i, sisReg->VBPart4[i]); 950#ifdef TWDEBUG 951 xf86DrvMsg(0, X_INFO, "301xSave: Part4 0x%02x = 0x%02x\n", i, sisReg->VBPart4[i]); 952#endif 953 } 954} 955 956/* Save SiS301 bridge register contents */ 957static void 958SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) 959{ 960 SISPtr pSiS = SISPTR(pScrn); 961 int Part1max, Part2max, Part3max, Part4max; 962 963 /* Highest register number to save/restore */ 964 if(pSiS->VGAEngine == SIS_300_VGA) Part1max = 0x1d; 965 else Part1max = 0x2e; /* 0x23, but we also need 2d-2e */ 966 967 Part2max = 0x45; 968 Part3max = 0x3e; 969 Part4max = 0x1b; 970 971 SiSVBSave(pScrn, sisReg, Part1max, Part2max, Part3max, Part4max); 972 973 sisReg->VBPart2[0x00] &= ~0x20; /* Disable VB Processor */ 974 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ 975} 976 977/* Restore SiS301 bridge register contents */ 978static void 979SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 980{ 981 SISPtr pSiS = SISPTR(pScrn); 982 int Part1max, Part2max, Part3max, Part4max; 983 984 /* Highest register number to save/restore */ 985 if(pSiS->VGAEngine == SIS_300_VGA) Part1max = 0x1d; 986 else Part1max = 0x23; 987 988 Part2max = 0x45; 989 Part3max = 0x3e; 990 Part4max = 0x1b; 991 992 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 993 SiSSetLVDSetc(pSiS->SiS_Pr); 994 SiS_GetVBType(pSiS->SiS_Pr); 995 SiS_DisableBridge(pSiS->SiS_Pr); 996 SiS_UnLockCRT2(pSiS->SiS_Pr); 997 998 /* Pre-restore Part1 */ 999 outSISIDXREG(SISPART1, 0x04, 0x00); 1000 outSISIDXREG(SISPART1, 0x05, 0x00); 1001 outSISIDXREG(SISPART1, 0x06, 0x00); 1002 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]); 1003 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]); 1004 1005 /* Pre-restore Part4 */ 1006 outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]); 1007 outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]); 1008 1009 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) && 1010 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ 1011 SiS_LockCRT2(pSiS->SiS_Pr); 1012 return; 1013 } 1014 1015 /* Restore Part1 */ 1016 SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02])); 1017 if(pSiS->VGAEngine == SIS_315_VGA) { 1018 /* Restore extra registers on 315 series */ 1019 SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C])); 1020 } 1021 1022 /* Restore Part2 */ 1023 SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00])); 1024 1025 /* Restore Part3 */ 1026 SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00])); 1027 1028 /* Restore Part4 */ 1029 SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E])); 1030 SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13])); 1031 1032 /* Post-restore Part4 (CRT2VCLK) */ 1033 outSISIDXREG(SISPART4, 0x0A, 0x01); 1034 outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]); 1035 outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]); 1036 outSISIDXREG(SISPART4, 0x12, 0x00); 1037 outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]); 1038 1039 SiS_EnableBridge(pSiS->SiS_Pr); 1040 SiS_DisplayOn(pSiS->SiS_Pr); 1041 SiS_LockCRT2(pSiS->SiS_Pr); 1042} 1043 1044/* Save SiS30xB/30xLV bridge register contents */ 1045static void 1046SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1047{ 1048 SISPtr pSiS = SISPTR(pScrn); 1049 int Part1max, Part2max, Part3max, Part4max; 1050 1051 Part1max = 0x60; 1052 Part2max = 0x4d; 1053 Part3max = 0x3e; 1054 Part4max = 0x23; 1055 if(pSiS->VBFlags2 & (VB2_301LV | VB2_302LV)) { 1056 Part4max = 0x34; 1057 } else if(pSiS->VBFlags2 & (VB2_301C | VB2_302ELV)) { 1058 Part2max = 0xff; 1059 Part4max = 0x3c; 1060 } /* TODO for 307 */ 1061 1062 SiSVBSave(pScrn, sisReg, Part1max, Part2max, Part3max, Part4max); 1063 1064 sisReg->VBPart2[0x00] &= ~0x20; /* Disable VB Processor */ 1065 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ 1066} 1067 1068/* Restore SiS30xB/30xLV bridge register contents */ 1069static void 1070SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1071{ 1072 SISPtr pSiS = SISPTR(pScrn); 1073 int Part1max, Part2max, Part3max, Part4max; 1074 1075 Part1max = 0x23; 1076 Part2max = 0x4d; 1077 Part3max = 0x3e; 1078 Part4max = 0x22; 1079 if(pSiS->VBFlags2 & (VB2_301LV|VB2_302LV)) { 1080 Part4max = 0x34; 1081 } else if(pSiS->VBFlags2 & (VB2_301C|VB2_302ELV)) { 1082 Part2max = 0xff; 1083 Part4max = 0x3c; 1084 } /* TODO for 307 */ 1085 1086 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 1087 SiSSetLVDSetc(pSiS->SiS_Pr); 1088 SiS_GetVBType(pSiS->SiS_Pr); 1089 SiS_DisableBridge(pSiS->SiS_Pr); 1090 SiS_UnLockCRT2(pSiS->SiS_Pr); 1091 1092 /* Pre-restore Part1 */ 1093 outSISIDXREG(SISPART1, 0x04, 0x00); 1094 outSISIDXREG(SISPART1, 0x05, 0x00); 1095 outSISIDXREG(SISPART1, 0x06, 0x00); 1096 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0x00]); 1097 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[0x01]); 1098 /* Mode reg 0x01 became 0x2e on 315 series (0x01 still contains FIFO) */ 1099 if(pSiS->VGAEngine == SIS_315_VGA) { 1100 outSISIDXREG(SISPART1, 0x2e, sisReg->VBPart1[0x2e]); 1101 } 1102 1103 /* Pre-restore Part4 */ 1104 outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]); 1105 outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]); 1106 1107 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) && 1108 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ 1109 SiS_LockCRT2(pSiS->SiS_Pr); 1110 return; 1111 } 1112 1113 /* Restore Part1 */ 1114 SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02])); 1115 if(pSiS->VGAEngine == SIS_315_VGA) { 1116 SetBlock(SISPART1, 0x2C, 0x2D, &(sisReg->VBPart1[0x2C])); 1117 SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35])); 1118 if((pSiS->ChipFlags & SiSCF_Is65x) || (pSiS->ChipType >= SIS_661)) { 1119 outSISIDXREG(SISPART1, 0x4c, sisReg->VBPart1[0x4c]); 1120 } 1121 outSISIDXREG(SISPART1, 0x2e, sisReg->VBPart1[0x2e] & 0x7f); 1122 } 1123 1124 /* Restore Part2 */ 1125 SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00])); 1126 1127 /* Restore Part3 */ 1128 SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00])); 1129 1130 /* Restore Part4 */ 1131 SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E])); 1132 SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13])); 1133 1134 /* Post-restore Part4 (CRT2VCLK) */ 1135 outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]); 1136 outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]); 1137 outSISIDXREG(SISPART4, 0x12, 0x00); 1138 outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]); 1139 1140 SiS_EnableBridge(pSiS->SiS_Pr); 1141 SiS_DisplayOn(pSiS->SiS_Pr); 1142 SiS_LockCRT2(pSiS->SiS_Pr); 1143} 1144 1145/* Save LVDS bridge (+ Chrontel) register contents */ 1146static void 1147SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1148{ 1149 SISPtr pSiS = SISPTR(pScrn); 1150 int i; 1151 1152 /* Save Part1 */ 1153 for(i=0; i<0x46; i++) { 1154 inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]); 1155#ifdef TWDEBUG 1156 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1157 "LVDSSave: Part1Port 0x%02x = 0x%02x\n", 1158 i, sisReg->VBPart1[i]); 1159#endif 1160 } 1161 1162 /* Save Chrontel registers */ 1163 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1164 if(pSiS->ChrontelType == CHRONTEL_700x) { 1165 for(i=0; i<0x1D; i++) { 1166 sisReg->ch70xx[i] = SiS_GetCH700x(pSiS->SiS_Pr, ch700xidx[i]); 1167#ifdef TWDEBUG 1168 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1169 "LVDSSave: Chrontel 0x%02x = 0x%02x\n", 1170 ch700xidx[i], sisReg->ch70xx[i]); 1171#endif 1172 } 1173 } else { 1174 for(i=0; i<35; i++) { 1175 sisReg->ch70xx[i] = SiS_GetCH701x(pSiS->SiS_Pr, ch701xidx[i]); 1176#ifdef TWDEBUG 1177 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1178 "LVDSSave: Chrontel 0x%02x = 0x%02x\n", 1179 ch701xidx[i], sisReg->ch70xx[i]); 1180#endif 1181 } 1182 } 1183 } 1184 1185 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ 1186} 1187 1188/* Restore LVDS bridge (+ Chrontel) register contents */ 1189static void 1190SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1191{ 1192 SISPtr pSiS = SISPTR(pScrn); 1193 int i; 1194 1195 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 1196 SiSSetLVDSetc(pSiS->SiS_Pr); 1197 SiS_GetVBType(pSiS->SiS_Pr); 1198 SiS_DisableBridge(pSiS->SiS_Pr); 1199 if(pSiS->ChipType == SIS_730) { 1200 outSISIDXREG(SISPART1, 0x00, 0x80); 1201 } 1202 SiS_UnLockCRT2(pSiS->SiS_Pr); 1203 1204 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1205 /* Restore Chrontel registers */ 1206 if(pSiS->ChrontelType == CHRONTEL_700x) { 1207 for(i=0; i<0x11; i++) { 1208 SiS_SetCH700x(pSiS->SiS_Pr, ch700xidx[i] & 0xFF, sisReg->ch70xx[i]); 1209 } 1210 } else { 1211 for(i=0; i<34; i++) { 1212 SiS_SetCH701x(pSiS->SiS_Pr, ch701xidx[i] & 0xFF, sisReg->ch70xx[i]); 1213 } 1214 } 1215 } 1216 1217 /* pre-restore Part1 */ 1218 outSISIDXREG(SISPART1, 0x04, 0x00); 1219 outSISIDXREG(SISPART1, 0x05, 0x00); 1220 outSISIDXREG(SISPART1, 0x06, 0x00); 1221 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]); 1222 if(pSiS->VGAEngine == SIS_300_VGA) { 1223 outSISIDXREG(SISPART1, 0x01, (sisReg->VBPart1[1] | 0x80)); 1224 } else { 1225 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]); 1226 } 1227 1228 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) && 1229 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ 1230 SiS_LockCRT2(pSiS->SiS_Pr); 1231 return; 1232 } 1233 1234 /* Restore Part1 */ 1235 if(pSiS->VGAEngine == SIS_300_VGA) { 1236 outSISIDXREG(SISPART1, 0x02, (sisReg->VBPart1[2] | 0x40)); 1237 } else { 1238 outSISIDXREG(SISPART1, 0x02, sisReg->VBPart1[2]); 1239 } 1240 SetBlock(SISPART1, 0x03, 0x23, &(sisReg->VBPart1[0x03])); 1241 if(pSiS->VGAEngine == SIS_315_VGA) { 1242 SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C])); 1243 SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35])); /* Panel Link Scaler */ 1244 } 1245 1246 /* For 550 DSTN registers */ 1247 if(pSiS->DSTN || pSiS->FSTN) { 1248 SetBlock(SISPART1, 0x25, 0x2E, &(sisReg->VBPart1[0x25])); 1249 SetBlock(SISPART1, 0x30, 0x45, &(sisReg->VBPart1[0x30])); 1250 } 1251 1252 SiS_EnableBridge(pSiS->SiS_Pr); 1253 SiS_DisplayOn(pSiS->SiS_Pr); 1254 SiS_LockCRT2(pSiS->SiS_Pr); 1255} 1256 1257/* Restore output selection registers */ 1258void 1259SiSRestoreBridge(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1260{ 1261 SISPtr pSiS = SISPTR(pScrn); 1262 int i; 1263 1264#ifdef UNLOCK_ALWAYS 1265 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1266#endif 1267 1268 for(i = 0x30; i <= 0x3b; i++) { 1269 if(i == 0x34) continue; 1270 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); 1271 } 1272 1273 if(pSiS->VGAEngine == SIS_315_VGA) { 1274 outSISIDXREG(SISCR, pSiS->myCR63, sisReg->sisRegs3D4[pSiS->myCR63]); 1275 if(pSiS->ChipType < SIS_661) { 1276 outSISIDXREG(SISCR, 0x79, sisReg->sisRegs3D4[0x79]); 1277 } 1278 } 1279} 1280 1281/* Auxiliary function to find real memory clock (in Khz) */ 1282/* Not for 530/620 if UMA (on these, the mclk is stored in SR10) */ 1283int 1284SiSMclk(SISPtr pSiS) 1285{ 1286 int mclk=0; 1287 UChar Num, Denum, Base; 1288 1289 switch (pSiS->Chipset) { 1290 1291 case PCI_CHIP_SIS300: 1292 case PCI_CHIP_SIS540: 1293 case PCI_CHIP_SIS630: 1294 case PCI_CHIP_SIS315: 1295 case PCI_CHIP_SIS315H: 1296 case PCI_CHIP_SIS315PRO: 1297 case PCI_CHIP_SIS550: 1298 case PCI_CHIP_SIS650: 1299 case PCI_CHIP_SIS330: 1300 case PCI_CHIP_SIS660: 1301 case PCI_CHIP_SIS340: 1302 case PCI_CHIP_XGIXG20: 1303 case PCI_CHIP_XGIXG40: 1304 1305 /* Numerator */ 1306 inSISIDXREG(SISSR, 0x28, Num); 1307 mclk = 14318 * ((Num & 0x7f) + 1); 1308 1309 /* Denumerator */ 1310 inSISIDXREG(SISSR, 0x29, Denum); 1311 mclk = mclk / ((Denum & 0x1f) + 1); 1312 1313 /* Divider */ 1314 if((Num & 0x80) != 0) mclk *= 2; 1315 1316 /* Post-Scaler */ 1317 if((Denum & 0x80) == 0) { 1318 mclk = mclk / (((Denum & 0x60) >> 5) + 1); 1319 } else { 1320 mclk = mclk / ((((Denum & 0x60) >> 5) + 1) * 2); 1321 } 1322 break; 1323 1324 case PCI_CHIP_SIS5597: 1325 case PCI_CHIP_SIS6326: 1326 case PCI_CHIP_SIS530: 1327 default: 1328 /* Numerator */ 1329 inSISIDXREG(SISSR, 0x28, Num); 1330 mclk = 14318 * ((Num & 0x7f) + 1); 1331 1332 /* Denumerator */ 1333 inSISIDXREG(SISSR, 0x29, Denum); 1334 mclk = mclk / ((Denum & 0x1f) + 1); 1335 1336 /* Divider. Doesn't work on older cards */ 1337 if(pSiS->oldChipset >= OC_SIS5597) { 1338 if(Num & 0x80) mclk *= 2; 1339 } 1340 1341 /* Post-scaler. Values' meaning depends on SR13 bit 7 */ 1342 inSISIDXREG(SISSR, 0x13, Base); 1343 if((Base & 0x80) == 0) { 1344 mclk = mclk / (((Denum & 0x60) >> 5) + 1); 1345 } else { 1346 /* Values 00 and 01 are reserved */ 1347 if ((Denum & 0x60) == 0x40) mclk /= 6; 1348 if ((Denum & 0x60) == 0x60) mclk /= 8; 1349 } 1350 break; 1351 } 1352 1353 return(mclk); 1354} 1355 1356/* This estimates the CRT2 clock we are going to use. 1357 * The total bandwidth is to be reduced by the value 1358 * returned here in order to get an idea of the maximum 1359 * dotclock left for CRT1. 1360 * Since we don't know yet, what mode the user chose, 1361 * we return the maximum dotclock used by 1362 * - either the LCD attached, or 1363 * - TV 1364 * For VGA2, we share the bandwith equally. 1365 */ 1366static int 1367SiSEstimateCRT2Clock(ScrnInfoPtr pScrn, Bool FakeForCRT2) 1368{ 1369 SISPtr pSiS = SISPTR(pScrn); 1370 1371 if(pSiS->VBFlags & CRT2_LCD) { 1372 if(pSiS->VBLCDFlags & (VB_LCD_320x480 | VB_LCD_800x600 | VB_LCD_640x480)) { 1373 return 40000; 1374 } else if(pSiS->VBLCDFlags & (VB_LCD_1024x768 | VB_LCD_1024x600 | VB_LCD_1152x768)) { 1375 return 65000; 1376 } else if(pSiS->VBLCDFlags & VB_LCD_1280x720) { 1377 /* Fake clock; VGA (4:3) mode is 108, but uses only 75 for LCD */ 1378 if(FakeForCRT2) return 108000; 1379 else return 75000; 1380 } else if(pSiS->VBLCDFlags & VB_LCD_1280x768) { 1381 /* Fake clock; VGA (4:3) mode is 108, but uses only 81 for LCD */ 1382 if(FakeForCRT2) return 108000; 1383 else return 81000; 1384 } else if(pSiS->VBLCDFlags & VB_LCD_1280x800) { 1385 /* Fake clock; VGA (4:3) mode is 108, but uses only 83 for LCD */ 1386 if(FakeForCRT2) return 108000; 1387 else return 83000; 1388 } else if(pSiS->VBLCDFlags & VB_LCD_1280x854) { 1389 /* Fake clock; VGA (4:3) mode is 108, but uses only 84 for LCD */ 1390 if(FakeForCRT2) return 108000; 1391 else return 84000; 1392 } else if(pSiS->VBLCDFlags & (VB_LCD_1280x1024 | VB_LCD_1280x960)) { 1393 return 108000; 1394 } else if(pSiS->VBLCDFlags & VB_LCD_1400x1050) { 1395 /* Fake clock; VGA mode is 122, but uses only 108 for LCD */ 1396 if(FakeForCRT2) return 123000; 1397 else return 108000; 1398 } else if(pSiS->VBLCDFlags & VB_LCD_1680x1050) { 1399 /* Fake clock; VGA mode is 147, but uses only 122 for LCD */ 1400 if(FakeForCRT2) return 148000; 1401 else return 122000; 1402 } else if(pSiS->VBLCDFlags & VB_LCD_1600x1200) { 1403 return 162000; 1404 } else if((pSiS->VBLCDFlags & VB_LCD_CUSTOM) && (pSiS->SiS_Pr->CP_MaxClock)) { 1405 return pSiS->SiS_Pr->CP_MaxClock; 1406 } else { 1407 if(pSiS->VBFlags2 & VB2_30xC) return 162000; 1408 else return 108000; 1409 } 1410 } else if(pSiS->VBFlags & CRT2_TV) { 1411 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1412 switch(pSiS->VGAEngine) { 1413 case SIS_300_VGA: 1414 return 50000; /* 700x: <= 800x600 */ 1415 case SIS_315_VGA: 1416 default: 1417 return 70000; /* 701x: <= 1024x768 */ 1418 } 1419 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1420 if(pSiS->SiS_SD_Flags & (SiS_SD_SUPPORTYPBPR|SiS_SD_SUPPORTHIVISION)) { 1421 if(FakeForCRT2) return 108000; /* 1280x1024@60 (faked) */ 1422 else return 75000; /* Really used clock */ 1423 } else { 1424 return 70000; 1425 } 1426 } 1427 } 1428 1429 return 0; 1430} 1431 1432/* Calculate the maximum dotclock */ 1433int SiSMemBandWidth(ScrnInfoPtr pScrn, Bool IsForCRT2) 1434{ 1435 SISPtr pSiS = SISPTR(pScrn); 1436#ifdef SISDUALHEAD 1437 SISEntPtr pSiSEnt = pSiS->entityPrivate; 1438#endif 1439 int bus = pSiS->BusWidth; 1440 int mclk = pSiS->MemClock; 1441 int bpp = pSiS->CurrentLayout.bitsPerPixel; 1442 int max = 0; 1443 float magic = 0.0, total; 1444 int bytesperpixel = (bpp + 7) / 8; 1445 float crt2used, maxcrt2; 1446 int crt2clock; 1447 Bool DHM, GetForCRT1; 1448#ifdef __SUNPRO_C 1449#define const 1450#endif 1451 const float magicDED[4] = { 1.2, 1.368421, 2.263158, 1.2}; 1452 const float magicINT[4] = { 1.441177, 1.441177, 2.588235, 1.441177 }; 1453#ifdef __SUNPRO_C 1454#undef const 1455#endif 1456 1457 switch(pSiS->Chipset) { 1458 1459 case PCI_CHIP_SIS5597: 1460 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; 1461 if(total > 135000) total = 135000; 1462 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1463 "Maximum pixel clock at %d bpp is %g MHz\n", 1464 bpp, total/1000); 1465 return(int)(total); 1466 1467 case PCI_CHIP_SIS6326: 1468 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; 1469 if(total > 175500) total = 175500; 1470 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1471 "Maximum pixel clock at %d bpp is %g MHz\n", 1472 bpp, total/1000); 1473 return(int)(total); 1474 1475 case PCI_CHIP_SIS530: 1476 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; 1477 if(total > 230000) total = 230000; 1478 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1479 "Maximum pixel clock at %d bpp is %g MHz\n", 1480 bpp, total/1000); 1481 return(int)(total); 1482 1483 case PCI_CHIP_SIS300: 1484 case PCI_CHIP_SIS540: 1485 case PCI_CHIP_SIS630: 1486 case PCI_CHIP_SIS315: 1487 case PCI_CHIP_SIS315H: 1488 case PCI_CHIP_SIS315PRO: 1489 case PCI_CHIP_SIS550: 1490 case PCI_CHIP_SIS650: 1491 case PCI_CHIP_SIS330: 1492 case PCI_CHIP_SIS660: 1493 case PCI_CHIP_SIS340: 1494 case PCI_CHIP_XGIXG20: 1495 case PCI_CHIP_XGIXG40: 1496 switch(pSiS->Chipset) { 1497 case PCI_CHIP_SIS300: 1498 magic = magicDED[bus/64]; 1499 max = 540000; 1500 break; 1501 case PCI_CHIP_SIS540: 1502 case PCI_CHIP_SIS630: 1503 magic = magicINT[bus/64]; 1504 max = 540000; 1505 break; 1506 case PCI_CHIP_SIS315: 1507 case PCI_CHIP_SIS315H: 1508 case PCI_CHIP_SIS315PRO: 1509 case PCI_CHIP_SIS330: 1510 magic = magicDED[bus/64]; 1511 max = 780000; 1512 break; 1513 case PCI_CHIP_SIS550: 1514 magic = magicINT[bus/64]; 1515 max = 610000; 1516 break; 1517 case PCI_CHIP_SIS650: 1518 magic = magicINT[bus/64]; 1519 max = 680000; 1520 break; 1521 case PCI_CHIP_SIS660: 1522 if((pSiS->ChipType >= SIS_660) && 1523 (pSiS->ChipFlags & SiSCF_760LFB)) { 1524 magic = magicDED[bus/64]; 1525 } else { 1526 magic = magicINT[bus/64]; 1527 } 1528 max = 680000; 1529 case PCI_CHIP_SIS340: 1530 case PCI_CHIP_XGIXG40: 1531 magic = magicDED[bus/64]; 1532 max = 800000; 1533 break; 1534 case PCI_CHIP_XGIXG20: 1535 magic = 1.0; /* magicDED[bus/64]; */ 1536 max = 332000; 1537 break; 1538 } 1539 1540 PDEBUG(ErrorF("mclk: %d, bus: %d, magic: %g, bpp: %d\n", 1541 mclk, bus, magic, bpp)); 1542 1543 total = mclk * bus / bpp; 1544 1545 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1546 "Memory bandwidth at %d bpp is %g MHz\n", bpp, total/1000); 1547 1548 if((pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 1549 1550 maxcrt2 = 135000; 1551 if(pSiS->VBFlags2 & (VB2_301B|VB2_302B)) maxcrt2 = 162000; 1552 else if(pSiS->VBFlags2 & VB2_301C) maxcrt2 = 203000; 1553 else if(pSiS->VBFlags2 & VB2_307T) maxcrt2 = 203000; /* TODO */ 1554 /* if(pSiS->VBFlags2 & VB2_30xBDH) maxcrt2 = 100000; 1555 Ignore 301B-DH here; seems the current version is like 1556 301B anyway */ 1557 1558 crt2used = 0.0; 1559 crt2clock = SiSEstimateCRT2Clock(pScrn, IsForCRT2); 1560 if(crt2clock) { 1561 crt2used = crt2clock + 2000; 1562 } 1563 DHM = FALSE; 1564 GetForCRT1 = FALSE; 1565 1566#ifdef SISDUALHEAD 1567 if((pSiS->DualHeadMode) && (pSiSEnt)) { 1568 DHM = TRUE; 1569 if(pSiS->SecondHead) GetForCRT1 = TRUE; 1570 } 1571#endif 1572#ifdef SISMERGED 1573 if(pSiS->MergedFB && IsForCRT2) { 1574 DHM = TRUE; 1575 GetForCRT1 = FALSE; 1576 } 1577#endif 1578 1579 if(DHM) { 1580 1581 if(!GetForCRT1) { 1582 1583 /* First head = CRT2 */ 1584 1585 if(crt2clock) { 1586 /* We use the mem bandwidth as max clock; this 1587 * might exceed the 70% limit a bit, but that 1588 * does not matter; we take care of that limit 1589 * when we calc CRT1. Overall, we might use up 1590 * to 85% of the memory bandwidth, which seems 1591 * enough to use accel and video. 1592 * The "* macic" is just to compensate the 1593 * calculation below. 1594 */ 1595 total = crt2used * magic; 1596 1597 } else { 1598 /* We don't know about the second head's 1599 * depth yet. So we assume it uses the 1600 * same. But since the maximum dotclock 1601 * is limited on CRT2, we can assume a 1602 * maximum here. 1603 */ 1604 if((total / 2) > (maxcrt2 + 2000)) { 1605 total = (maxcrt2 + 2000) * magic; 1606 crt2used = maxcrt2 + 2000; 1607 } else { 1608 total /= 2; 1609 crt2used = total; 1610 } 1611 1612 } 1613 1614 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1615 "Bandwidth reserved for CRT2 is %g MHz\n", 1616 crt2used/1000); 1617 1618 } else { 1619#ifdef SISDUALHEAD 1620 /* Second head = CRT1 */ 1621 1622 /* Now We know about the first head's depth, 1623 * so we can calculate more accurately. 1624 */ 1625 1626 if(crt2clock) { 1627 total -= (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp); 1628 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1629 "Bandwidth reserved for CRT2 at %d bpp is %g Mhz\n", 1630 bpp, 1631 (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000); 1632 } else { 1633 total -= (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp); 1634 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1635 "Bandwidth reserved for CRT2 at %d bpp is %d Mhz\n", 1636 bpp, 1637 (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000); 1638 } 1639 1640 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1641 "Bandwidth available for CRT1 is %g MHz\n", total/1000); 1642#endif 1643 } 1644 1645 } else { 1646 1647 if(crt2clock) { 1648 total -= crt2used; 1649 } else { 1650 if((total / 2) > (maxcrt2 + 2000)) { 1651 total -= (maxcrt2 + 2000); 1652 crt2used = maxcrt2 + 2000; 1653 } else { 1654 total /= 2; 1655 crt2used = total; 1656 } 1657 } 1658 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1659 "Bandwidth reserved for CRT2 is %g Mhz\n", crt2used/1000); 1660 1661 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1662 "Bandwidth available for CRT1 is %g MHz\n", total/1000); 1663 1664 } 1665 1666 } 1667 1668 total /= magic; 1669 if(total > (max / 2)) total = max / 2; 1670 return(int)(total); 1671 1672 default: 1673 return(135000); 1674 } 1675} 1676 1677/* Load the palette. We do this for all supported color depths 1678 * in order to support gamma correction. We hereby convert the 1679 * given colormap to a complete 24bit color palette and enable 1680 * the correspoding bit in SR7 to enable the 24bit lookup table. 1681 * Gamma correction for CRT2 is only supported on SiS video bridges. 1682 * There are there 6-bit-RGB values submitted even if bpp is 16 and 1683 * weight is 565, because SetWeight() sets rgbBits to the maximum 1684 * (which is 6 in the 565 case). 1685 */ 1686void 1687SISLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 1688 VisualPtr pVisual) 1689{ 1690 SISPtr pSiS = SISPTR(pScrn); 1691 int i, j, index; 1692 int myshift = 8 - pScrn->rgbBits; 1693 UChar backup = 0; 1694 Bool dogamma1 = pSiS->CRT1gamma; 1695 Bool resetxvgamma = FALSE; 1696#ifdef SISDUALHEAD 1697 SISEntPtr pSiSEnt = pSiS->entityPrivate; 1698 1699 if(pSiS->DualHeadMode) dogamma1 = pSiSEnt->CRT1gamma; 1700#endif 1701 1702 PDEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LoadPalette()\n")); 1703 1704#ifdef SISDUALHEAD 1705 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 1706#endif 1707 1708 if(pSiS->VGAEngine == SIS_315_VGA) { 1709 inSISIDXREG(SISSR, 0x1f, backup); 1710 andSISIDXREG(SISSR, 0x1f, 0xe7); 1711 if( (pSiS->XvGamma) && 1712 (pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA) && 1713 ((pSiS->CurrentLayout.depth == 16) || 1714 (pSiS->CurrentLayout.depth == 24)) ) { 1715 orSISIDXREG(SISSR, 0x1f, 0x10); 1716 resetxvgamma = TRUE; 1717 } 1718 } 1719 1720 switch(pSiS->CurrentLayout.depth) { 1721 case 15: 1722 if(dogamma1) { 1723 orSISIDXREG(SISSR, 0x07, 0x04); 1724 /* 315/330: depth 15 not supported, no MMIO code needed */ 1725 for(i=0; i<numColors; i++) { 1726 index = indices[i]; 1727 if(index < 32) { /* Paranoia */ 1728 for(j=0; j<8; j++) { 1729 outSISREG(SISCOLIDX, (index << 3) + j); 1730 outSISREG(SISCOLDATA, colors[index].red << myshift); 1731 outSISREG(SISCOLDATA, colors[index].green << myshift); 1732 outSISREG(SISCOLDATA, colors[index].blue << myshift); 1733 } 1734 } 1735 } 1736 } else { 1737 andSISIDXREG(SISSR, 0x07, ~0x04); 1738 } 1739 break; 1740 case 16: 1741 if(dogamma1) { 1742 orSISIDXREG(SISSR, 0x07, 0x04); 1743 if(pSiS->ChipFlags & SiSCF_MMIOPalette) { 1744 for(i=0; i<numColors; i++) { 1745 index = indices[i]; 1746 if(index < 64) { /* Paranoia */ 1747 for(j=0; j<4; j++) { 1748 SIS_MMIO_OUT32(pSiS->IOBase, 0x8570, 1749 (colors[index].green << (myshift + 8)) | 1750 (colors[index >> 1].blue << (myshift + 16)) | 1751 (colors[index >> 1].red << myshift) | 1752 (((index << 2) + j) << 24)); 1753 } 1754 } 1755 } 1756 } else { 1757 for(i=0; i<numColors; i++) { 1758 index = indices[i]; 1759 if(index < 64) { /* Paranoia */ 1760 for(j=0; j<4; j++) { 1761 outSISREG(SISCOLIDX, (index << 2) + j); 1762 outSISREG(SISCOLDATA, colors[index >> 1].red << myshift); 1763 outSISREG(SISCOLDATA, colors[index].green << myshift); 1764 outSISREG(SISCOLDATA, colors[index >> 1].blue << myshift); 1765 } 1766 } 1767 } 1768 } 1769 } else { 1770 andSISIDXREG(SISSR, 0x07, ~0x04); 1771 } 1772 break; 1773 case 24: 1774 if(dogamma1) { 1775 orSISIDXREG(SISSR, 0x07, 0x04); 1776 if(pSiS->ChipFlags & SiSCF_MMIOPalette) { 1777 for(i=0; i<numColors; i++) { 1778 index = indices[i]; 1779 if(index < 256) { /* Paranoia */ 1780 SIS_MMIO_OUT32(pSiS->IOBase, 0x8570, 1781 (colors[index].blue << 16) | 1782 (colors[index].green << 8) | 1783 (colors[index].red) | 1784 (index << 24)); 1785 } 1786 } 1787 } else { 1788 for(i=0; i<numColors; i++) { 1789 index = indices[i]; 1790 if(index < 256) { /* Paranoia */ 1791 outSISREG(SISCOLIDX, index); 1792 outSISREG(SISCOLDATA, colors[index].red); 1793 outSISREG(SISCOLDATA, colors[index].green); 1794 outSISREG(SISCOLDATA, colors[index].blue); 1795 } 1796 } 1797 } 1798 } else { 1799 andSISIDXREG(SISSR, 0x07, ~0x04); 1800 } 1801 break; 1802 default: 1803 andSISIDXREG(SISSR, 0x07, ~0x04); 1804 if(pSiS->ChipFlags & SiSCF_MMIOPalette) { 1805 for(i=0; i<numColors; i++) { 1806 index = indices[i]; 1807 SIS_MMIO_OUT32(pSiS->IOBase, 0x8570, 1808 ((colors[index].blue) << 16) | 1809 ((colors[index].green) << 8) | 1810 (colors[index].red) | 1811 (index << 24)); 1812 } 1813 } else { 1814 for(i=0; i<numColors; i++) { 1815 /* In pio mode, only 6 bits are supported */ 1816 index = indices[i]; 1817 outSISREG(SISCOLIDX, index); 1818 outSISREG(SISCOLDATA, colors[index].red >> 2); 1819 outSISREG(SISCOLDATA, colors[index].green >> 2); 1820 outSISREG(SISCOLDATA, colors[index].blue >> 2); 1821 } 1822 } 1823 } 1824 1825 if(pSiS->VGAEngine == SIS_315_VGA) { 1826 outSISIDXREG(SISSR, 0x1f, backup); 1827 inSISIDXREG(SISSR, 0x07, backup); 1828 if((backup & 0x04) && (resetxvgamma) && (pSiS->ResetXvGamma)) { 1829 (pSiS->ResetXvGamma)(pScrn); 1830 } 1831 } 1832 1833#ifdef SISDUALHEAD 1834 } 1835#endif 1836 1837#ifdef SISDUALHEAD 1838 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 1839#endif 1840 switch(pSiS->VGAEngine) { 1841 case SIS_300_VGA: 1842 case SIS_315_VGA: 1843 if(pSiS->VBFlags & CRT2_ENABLE) { 1844 /* Only the SiS bridges support a CRT2 palette */ 1845 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1846 if((pSiS->CRT2SepGamma) && (pSiS->crt2cindices) && (pSiS->crt2colors)) { 1847 SiS301LoadPalette(pScrn, numColors, pSiS->crt2cindices, pSiS->crt2colors, myshift); 1848 } else { 1849 SiS301LoadPalette(pScrn, numColors, indices, colors, myshift); 1850 } 1851 } 1852 } 1853 } 1854#ifdef SISDUALHEAD 1855 } 1856#endif 1857 1858} 1859 1860void 1861SiS_UpdateGammaCRT2(ScrnInfoPtr pScrn) 1862{ 1863 SISPtr pSiS = SISPTR(pScrn); 1864 1865 if((!pSiS->CRT2SepGamma) || (!pSiS->crt2cindices) || (!pSiS->crt2gcolortable)) return; 1866 1867#ifdef SISDUALHEAD 1868 if(pSiS->DualHeadMode) return; 1869#endif 1870 1871 SISCalculateGammaRampCRT2(pScrn); 1872 SiS301LoadPalette(pScrn, pSiS->CRT2ColNum, pSiS->crt2cindices, pSiS->crt2colors, (8 - pScrn->rgbBits)); 1873} 1874 1875static void 1876SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, int myshift) 1877{ 1878 SISPtr pSiS = SISPTR(pScrn); 1879 int i, j, index; 1880 Bool dogamma2 = pSiS->CRT2gamma; 1881#ifdef SISDUALHEAD 1882 SISEntPtr pSiSEnt = pSiS->entityPrivate; 1883 1884 if(pSiS->DualHeadMode) dogamma2 = pSiSEnt->CRT2gamma; 1885#endif 1886 1887 /* 301B-DH does not support a color palette for LCD */ 1888 if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) return; 1889 1890 switch(pSiS->CurrentLayout.depth) { 1891 case 15: 1892 if(dogamma2) { 1893 orSISIDXREG(SISPART4, 0x0d, 0x08); 1894 for(i=0; i<numColors; i++) { 1895 index = indices[i]; 1896 if(index < 32) { /* Paranoia */ 1897 for(j=0; j<8; j++) { 1898 outSISREG(SISCOL2IDX, (index << 3) + j); 1899 outSISREG(SISCOL2DATA, colors[index].red << myshift); 1900 outSISREG(SISCOL2DATA, colors[index].green << myshift); 1901 outSISREG(SISCOL2DATA, colors[index].blue << myshift); 1902 } 1903 } 1904 } 1905 } else { 1906 andSISIDXREG(SISPART4, 0x0d, ~0x08); 1907 } 1908 break; 1909 case 16: 1910 if(dogamma2) { 1911 orSISIDXREG(SISPART4, 0x0d, 0x08); 1912 for(i = 0; i < numColors; i++) { 1913 index = indices[i]; 1914 if(index < 64) { /* Paranoia */ 1915 for(j = 0; j < 4; j++) { 1916 outSISREG(SISCOL2IDX, (index << 2) + j); 1917 outSISREG(SISCOL2DATA, colors[index >> 1].red << myshift); 1918 outSISREG(SISCOL2DATA, colors[index].green << myshift); 1919 outSISREG(SISCOL2DATA, colors[index >> 1].blue << myshift); 1920 } 1921 } 1922 } 1923 } else { 1924 andSISIDXREG(SISPART4, 0x0d, ~0x08); 1925 } 1926 break; 1927 case 24: 1928 if(dogamma2) { 1929 orSISIDXREG(SISPART4, 0x0d, 0x08); 1930 for(i = 0; i < numColors; i++) { 1931 index = indices[i]; 1932 if(index < 256) { /* Paranoia */ 1933 outSISREG(SISCOL2IDX, index); 1934 outSISREG(SISCOL2DATA, colors[index].red); 1935 outSISREG(SISCOL2DATA, colors[index].green); 1936 outSISREG(SISCOL2DATA, colors[index].blue); 1937 } 1938 } 1939 } else { 1940 andSISIDXREG(SISPART4, 0x0d, ~0x08); 1941 } 1942 break; 1943 default: 1944 orSISIDXREG(SISPART4, 0x0d, 0x08); 1945 for(i = 0; i < numColors; i++) { 1946 index = indices[i]; 1947 outSISREG(SISCOL2IDX, index); 1948 outSISREG(SISCOL2DATA, colors[index].red); 1949 outSISREG(SISCOL2DATA, colors[index].green); 1950 outSISREG(SISCOL2DATA, colors[index].blue); 1951 } 1952 } 1953} 1954 1955void 1956SISDACPreInit(ScrnInfoPtr pScrn) 1957{ 1958 SISPtr pSiS = SISPTR(pScrn); 1959 Bool IsForCRT2 = FALSE; 1960 1961#ifdef SISDUALHEAD 1962 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) 1963 IsForCRT2 = TRUE; 1964#endif 1965 1966 pSiS->MaxClock = SiSMemBandWidth(pScrn, IsForCRT2); 1967 1968 switch (pSiS->Chipset) { 1969 case PCI_CHIP_SIS550: 1970 case PCI_CHIP_SIS315: 1971 case PCI_CHIP_SIS315H: 1972 case PCI_CHIP_SIS315PRO: 1973 case PCI_CHIP_SIS650: 1974 case PCI_CHIP_SIS330: 1975 case PCI_CHIP_SIS660: 1976 case PCI_CHIP_SIS340: 1977 case PCI_CHIP_XGIXG20: 1978 case PCI_CHIP_XGIXG40: 1979 pSiS->SiSSave = SiS315Save; 1980 pSiS->SiSRestore = SiS315Restore; 1981 break; 1982 case PCI_CHIP_SIS300: 1983 case PCI_CHIP_SIS540: 1984 case PCI_CHIP_SIS630: 1985 pSiS->SiSSave = SiS300Save; 1986 pSiS->SiSRestore = SiS300Restore; 1987 break; 1988 case PCI_CHIP_SIS5597: 1989 case PCI_CHIP_SIS6326: 1990 case PCI_CHIP_SIS530: 1991 default: 1992 pSiS->SiSSave = SiSSave; 1993 pSiS->SiSRestore = SiSRestore; 1994 break; 1995 } 1996} 1997 1998static void 1999SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr) 2000{ 2001 CARD8 index; 2002 2003 for(index = from; index <= to; index++, DataPtr++) { 2004 outSISIDXREG(port, index, *DataPtr); 2005 } 2006} 2007 2008void 2009SiS6326SetTVReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data) 2010{ 2011 SISPtr pSiS = SISPTR(pScrn); 2012 outSISIDXREG(SISCR, 0xE0, index); 2013 outSISIDXREG(SISCR, 0xE1, data); 2014#ifdef TWDEBUG 2015 xf86DrvMsg(0, X_INFO, "SiS6326: Setting Tv %02x to %02x\n", index, data); 2016#endif 2017} 2018 2019UChar 2020SiS6326GetTVReg(ScrnInfoPtr pScrn, CARD8 index) 2021{ 2022 SISPtr pSiS = SISPTR(pScrn); 2023 UChar data; 2024 2025 outSISIDXREG(SISCR, 0xE0, index); 2026 inSISIDXREG(SISCR, 0xE1, data); 2027 return(data); 2028} 2029 2030void 2031SiS6326SetXXReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data) 2032{ 2033 SISPtr pSiS = SISPTR(pScrn); 2034 outSISIDXREG(SISCR, 0xE2, index); 2035 outSISIDXREG(SISCR, 0xE3, data); 2036} 2037 2038UChar 2039SiS6326GetXXReg(ScrnInfoPtr pScrn, CARD8 index) 2040{ 2041 SISPtr pSiS = SISPTR(pScrn); 2042 UChar data; 2043 2044 outSISIDXREG(SISCR, 0xE2, index); 2045 inSISIDXREG(SISCR, 0xE3, data); 2046 return(data); 2047} 2048 2049UChar SiSGetCopyROP(int rop) 2050{ 2051 const UChar sisALUConv[] = 2052 { 2053 0x00, /* dest = 0; 0, GXclear, 0 */ 2054 0x88, /* dest &= src; DSa, GXand, 0x1 */ 2055 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ 2056 0xCC, /* dest = src; S, GXcopy, 0x3 */ 2057 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ 2058 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 2059 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ 2060 0xEE, /* dest |= src; DSo, GXor, 0x7 */ 2061 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ 2062 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ 2063 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 2064 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ 2065 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ 2066 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ 2067 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ 2068 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 2069 }; 2070 2071 return(sisALUConv[rop]); 2072} 2073 2074UChar SiSGetPatternROP(int rop) 2075{ 2076 const UChar sisPatALUConv[] = 2077 { 2078 0x00, /* dest = 0; 0, GXclear, 0 */ 2079 0xA0, /* dest &= src; DPa, GXand, 0x1 */ 2080 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ 2081 0xF0, /* dest = src; P, GXcopy, 0x3 */ 2082 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ 2083 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 2084 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ 2085 0xFA, /* dest |= src; DPo, GXor, 0x7 */ 2086 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ 2087 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ 2088 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 2089 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ 2090 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ 2091 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ 2092 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ 2093 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 2094 }; 2095 2096 return(sisPatALUConv[rop]); 2097} 2098