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