1/* 2 * DAC helper functions (Save/Restore, MemClk, etc) 3 * 4 * Copyright (C) 2001-2004 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 EXPRESSED 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 * XGI_compute_vclk(), XGICalcClock() and parts of XGIMclk(): 31 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England 32 * Written by: 33 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 34 * Mike Chapman <mike@paranoia.com>, 35 * Juanjo Santamarta <santamarta@ctv.es>, 36 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 37 * David Thomas <davtom@dream.org.uk>, 38 * Thomas Winischhofer <thomas@winischhofer.net>. 39 * Licensed under the terms of the XFree86 license 40 * (http://www.xfree86.org/current/LICENSE1.html) 41 * 42 */ 43 44#ifdef HAVE_CONFIG_H 45#include "config.h" 46#endif 47 48#include "xf86.h" 49#include "xf86_OSproc.h" 50#include "xorgVersion.h" 51#include "xf86PciInfo.h" 52#include "xf86Pci.h" 53#include "xf86DDC.h" 54 55#include "xgi.h" 56#include "xgi_dac.h" 57#include "xgi_regs.h" 58#include "xgi_vb.h" 59 60static void Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) ; 61static void Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) ; 62static void Volari_Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, 63 unsigned short *Low, unsigned short *High); 64int 65compute_vclk( 66 int Clock, 67 int *out_n, 68 int *out_dn, 69 int *out_div, 70 int *out_sbit, 71 int *out_scale) 72{ 73 float f,x,y,t, error, min_error; 74 int n, dn, best_n=0, best_dn=0; 75 76 /* 77 * Rules 78 * 79 * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator) 80 * Factor = (Divider/Post Scalar) 81 * Divider is 1 or 2 82 * Post Scalar is 1, 2, 3, 4, 6 or 8 83 * Numberator ranged from 1 to 128 84 * DeNumerator ranged from 1 to 32 85 * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz 86 * b. Post Scalar selected from 1, 2, 4 or 8 first. 87 * c. DeNumerator selected from 2. 88 * 89 * According to rule a and b, the VCO ranges that can be scaled by 90 * rule b are: 91 * 150 - 250 (Factor = 1) 92 * 75 - 125 (Factor = 2) 93 * 37.5 - 62.5 (Factor = 4) 94 * 18.75 - 31.25 (Factor = 8) 95 * 96 * The following ranges use Post Scalar 3 or 6: 97 * 125 - 150 (Factor = 1.5) 98 * 62.5 - 75 (Factor = 3) 99 * 31.25 - 37.5 (Factor = 6) 100 * 101 * Steps: 102 * 1. divide the Clock by 2 until the Clock is less or equal to 31.25. 103 * 2. if the divided Clock is range from 18.25 to 31.25, than 104 * the Factor is 1, 2, 4 or 8. 105 * 3. if the divided Clock is range from 15.625 to 18.25, than 106 * the Factor is 1.5, 3 or 6. 107 * 4. select the Numberator and DeNumberator with minimum deviation. 108 * 109 * ** this function can select VCLK ranged from 18.75 to 250 Mhz 110 */ 111 f = (float) Clock; 112 f /= 1000.0; 113 if ((f > 250.0) || (f < 18.75)) 114 return 0; 115 116 min_error = f; 117 y = 1.0; 118 x = f; 119 while (x > 31.25) { 120 y *= 2.0; 121 x /= 2.0; 122 } 123 if (x >= 18.25) { 124 x *= 8.0; 125 y = 8.0 / y; 126 } else if (x >= 15.625) { 127 x *= 12.0; 128 y = 12.0 / y; 129 } 130 131 t = y; 132 if (t == (float) 1.5) { 133 *out_div = 2; 134 t *= 2.0; 135 } else { 136 *out_div = 1; 137 } 138 if (t > (float) 4.0) { 139 *out_sbit = 1; 140 t /= 2.0; 141 } else { 142 *out_sbit = 0; 143 } 144 145 *out_scale = (int) t; 146 147 for (dn=2;dn<=32;dn++) { 148 for (n=1;n<=128;n++) { 149 error = x; 150 error -= ((float) 14.318 * (float) n / (float) dn); 151 if (error < (float) 0) 152 error = -error; 153 if (error < min_error) { 154 min_error = error; 155 best_n = n; 156 best_dn = dn; 157 } 158 } 159 } 160 *out_n = best_n; 161 *out_dn = best_dn; 162 PDEBUG(ErrorF("compute_vclk: Clock=%d, n=%d, dn=%d, div=%d, sbit=%d," 163 " scale=%d\n", Clock, best_n, best_dn, *out_div, 164 *out_sbit, *out_scale)); 165 return 1; 166} 167 168void 169XGICalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk) 170{ 171/* XGIPtr pXGI = XGIPTR(pScrn); */ 172 int M, N, P , PSN, VLD , PSNx ; 173 int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; 174 double abest = 42.0; 175 double target; 176 double Fvco, Fout; 177 double error, aerror; 178#ifdef DEBUG 179 double bestFout; 180#endif 181 182 /* 183 * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) 184 * 185 * M = Numerator [1:128] 186 * N = DeNumerator [1:32] 187 * VLD = Divider (Vco Loop Divider) : divide by 1, 2 188 * P = Post Scaler : divide by 1, 2, 3, 4 189 * PSN = Pre Scaler (Reference Divisor Select) 190 * 191 * result in vclk[] 192 */ 193#define Midx 0 194#define Nidx 1 195#define VLDidx 2 196#define Pidx 3 197#define PSNidx 4 198#define Fref 14318180 199/* stability constraints for internal VCO -- MAX_VCO also determines 200 * the maximum Video pixel clock */ 201#define MIN_VCO Fref 202#define MAX_VCO 135000000 203#define MAX_VCO_5597 353000000 204#define MAX_PSN 0 /* no pre scaler for this chip */ 205#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ 206 207 int M_min = 2; 208 int M_max = 128; 209 210 target = clock * 1000; 211 212 for(PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { 213 214 int low_N, high_N; 215 double FrefVLDPSN; 216 217 PSN = !PSNx ? 1 : 4; 218 219 low_N = 2; 220 high_N = 32; 221 222 for(VLD = 1 ; VLD <= max_VLD ; VLD++) { 223 224 FrefVLDPSN = (double)Fref * VLD / PSN; 225 226 for(N = low_N; N <= high_N; N++) { 227 double tmp = FrefVLDPSN / N; 228 229 for(P = 1; P <= 4; P++) { 230 double Fvco_desired = target * ( P ); 231 double M_desired = Fvco_desired / tmp; 232 233 /* Which way will M_desired be rounded? 234 * Do all three just to be safe. 235 */ 236 int M_low = M_desired - 1; 237 int M_hi = M_desired + 1; 238 239 if(M_hi < M_min || M_low > M_max) continue; 240 241 if(M_low < M_min) M_low = M_min; 242 243 if(M_hi > M_max) M_hi = M_max; 244 245 for(M = M_low; M <= M_hi; M++) { 246 Fvco = tmp * M; 247 if(Fvco <= MIN_VCO) continue; 248 if(Fvco > MAX_VCO) break; 249 250 Fout = Fvco / ( P ); 251 252 error = (target - Fout) / target; 253 aerror = (error < 0) ? -error : error; 254 if(aerror < abest) { 255 abest = aerror; 256 bestM = M; 257 bestN = N; 258 bestP = P; 259 bestPSN = PSN; 260 bestVLD = VLD; 261#ifdef DEBUG 262 bestFout = Fout; 263#endif 264 } 265#ifdef TWDEBUG 266 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 267 "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", 268 (float)(clock / 1000.), M, N, P, VLD, PSN); 269 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 270 "Freq. set: %.2f MHz\n", Fout / 1.0e6); 271#endif 272 } 273 } 274 } 275 } 276 } 277 278 vclk[Midx] = bestM; 279 vclk[Nidx] = bestN; 280 vclk[VLDidx] = bestVLD; 281 vclk[Pidx] = bestP; 282 vclk[PSNidx] = bestPSN; 283/* 284 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 285 "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", 286 (float)(clock / 1000.), vclk[Midx], vclk[Nidx], vclk[VLDidx], 287 vclk[Pidx], vclk[PSNidx])); 288 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 289 "Freq. set: %.2f MHz\n", bestFout / 1.0e6)); 290 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 291 "VCO Freq.: %.2f MHz\n", bestFout*bestP / 1.0e6)); 292*/ 293 294} 295 296static void 297Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) 298{ 299 XGIPtr pXGI = XGIPTR(pScrn); 300 int vgaIOBase; 301 int i; 302 303 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 304 "Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg)\n")); 305 306 vgaHWGetIOBase(VGAHWPTR(pScrn)); 307 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 308 309#if !defined(__arm__) 310 outw(VGA_SEQ_INDEX, 0x8605); 311#else 312 moutl(XGISR, 0x8605); 313#endif 314 315 for (i = 0x06; i <= 0x3F; i++) { 316 /* outb(VGA_SEQ_INDEX, i); */ 317 outb(XGISR, i); 318 319 /* xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 320 "XR%02X Contents - %02X \n", i, inb(VGA_SEQ_DATA)); 321 xgiReg->xgiRegs3C4[i] = inb(VGA_SEQ_DATA); */ 322 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 323 "XR%02X Contents - %02X \n", i, inb(XGISR+1)); 324 xgiReg->xgiRegs3C4[i] = inb(XGISR+1); 325 } 326 327 for (i=0x19; i<0x5C; i++) { 328 inXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 329 } 330 331 /*xgiReg->xgiRegs3C2 = inb(0x3CC);*/ 332 333 xgiReg->xgiRegs3C2 = inb(pXGI->RelIO+0x4c); 334 335 for (i=0x19; i<0x5C; i++) { 336 inXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 337 } 338 339// yilin save the VB register 340 outXGIIDXREG(XGIPART1, 0x2f, 0x01); 341 342 for (i=0; i<0x50; i++) 343 { 344 inXGIIDXREG(XGIPART1, i, xgiReg->VBPart1[i]); 345 } 346 for (i=0; i<0x50; i++) 347 { 348 inXGIIDXREG(XGIPART2, i, xgiReg->VBPart2[i]); 349 } 350 for (i=0; i<0x50; i++) 351 { 352 inXGIIDXREG(XGIPART3, i, xgiReg->VBPart3[i]); 353 } 354 for (i=0; i<0x50; i++) 355 { 356 inXGIIDXREG(XGIPART4, i, xgiReg->VBPart4[i]); 357 } 358 359 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 360 "Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) Done\n")); 361 362} 363 364static void 365Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) 366{ 367 XGIPtr pXGI = XGIPTR(pScrn); 368 int vgaIOBase; 369 int i; 370 371 PDEBUG(ErrorF("--- Volari_Restore(). \n")) ; 372 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 373 "Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg)\n"); 374 375 vgaHWGetIOBase(VGAHWPTR(pScrn)); 376 vgaIOBase = VGAHWPTR(pScrn)->IOBase; 377 378 outXGIIDXREG(XGISR, 0x05, 0x86); 379 380 381#if 1 382 /* Jong@08112009; recover this line */ 383 /* Volari_DisableAccelerator(pScrn) ; */ 384#else 385 inXGIIDXREG(XGISR, 0x1E, temp); 386 387 if (temp & (SR1E_ENABLE_2D | SR1E_ENABLE_3D)) { 388 Volari_Idle(pXGI); 389 } 390 391 PDEBUG(XGIDumpRegs(pScrn)); 392 393 outXGIIDXREG(XGICR, 0x55, 0); 394 andXGIIDXREG(XGISR, 0x1E, 395 ~(SR1E_ENABLE_3D_TRANSFORM_ENGINE 396 | SR1E_ENABLE_2D 397 | SR1E_ENABLE_3D)); 398 PDEBUG(XGIDumpRegs(pScrn)); 399#endif 400 401 PDEBUG(XGIDumpRegs(pScrn)) ; //yilin 402 403 for (i = 0x19; i < 0x5C; i++) { 404 /* Jong 09/19/2007; added for ??? */ 405 if((i!=0x48 && i!=0x4a)|| ((pXGI->Chipset != PCI_CHIP_XGIXG20)&&(pXGI->Chipset != PCI_CHIP_XGIXG21)&&(pXGI->Chipset != PCI_CHIP_XGIXG27))) 406 outXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 407 } 408 409 for (i = 0x06; i <= 0x3F; i++) { 410 /* if( !(i==0x16 || i==0x18 || i==0x19 || i==0x28 || i==0x29 || i==0x2E || i==0x2F) ) { */ 411 if( !(i==0x16 ) ) { 412 /* outb(VGA_SEQ_INDEX,i); */ 413 outb(XGISR,i); 414 415 /* xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 416 "XR%X Contents - %02X ", i, inb(VGA_SEQ_DATA)); 417 418 outb(VGA_SEQ_DATA,xgiReg->xgiRegs3C4[i]); 419 420 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 421 "Restore to - %02X Read after - %02X\n", 422 xgiReg->xgiRegs3C4[i], inb(VGA_SEQ_DATA)); */ 423 424 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 425 "XR%X Contents - %02X ", i, inb(XGISR+1)); 426 427 outb(XGISR+1,xgiReg->xgiRegs3C4[i]); 428 429 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 430 "Restore to - %02X Read after - %02X\n", 431 xgiReg->xgiRegs3C4[i], inb(XGISR+1)); 432 } 433 } 434 435 436#if 0 437 // yilin restore the VB register 438 outXGIIDXREG(XGIPART1, 0x2f, 0x01); 439 for (i=0; i<0x50; i++) 440 { 441 outXGIIDXREG(XGIPART1, i, xgiReg->VBPart1[i]); 442 } 443 for (i=0; i<0x50; i++) 444 { 445 outXGIIDXREG(XGIPART2, i, xgiReg->VBPart2[i]); 446 } 447 for (i=0; i<0x50; i++) 448 { 449 outXGIIDXREG(XGIPART3, i, xgiReg->VBPart3[i]); 450 } 451 for (i=0; i<0x50; i++) 452 { 453 outXGIIDXREG(XGIPART4, i, xgiReg->VBPart4[i]); 454 } 455#endif 456 457 outb(pXGI->RelIO+0x42, xgiReg->xgiRegs3C2); 458 459 /* MemClock needs this to take effect */ 460 461#if !defined(__arm__) 462 outw(VGA_SEQ_INDEX, 0x0100); /* Synchronous Reset */ 463#else 464 moutl(XGISR, 0x0100); /* Synchronous Reset */ 465#endif 466 467 PDEBUG(XGIDumpRegs(pScrn)) ; //yilin 468 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 469 "Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) Done\n"); 470 471 472} 473 474static void 475Volari_Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, 476 unsigned short *Low, unsigned short *High) 477{ 478 XGIPtr pXGI = XGIPTR(pScrn); 479 480 orXGIIDXREG(XGISR, 0x3D, 0x01); 481} 482 483 484/** 485 * Calculate available memory bandwidth for an XG40 series chip. 486 * 487 * \sa XG40_MemBandWidth 488 */ 489static int XG40_MemBandWidth(ScrnInfoPtr pScrn) 490{ 491 static const float magic315[4] = { 1.2, 1.368421, 2.263158, 1.2 }; 492 XGIPtr pXGI = XGIPTR(pScrn); 493 const int bus = (pXGI->BusWidth > 128) ? 128 : pXGI->BusWidth; 494 const int mclk = pXGI->MemClock; 495 const int bpp = pScrn->bitsPerPixel; 496 const float magic = magic315[bus / 64]; 497 float total = (mclk * bus) / bpp; 498 499 PDEBUG5(ErrorF("mclk: %d, bus: %d, magic: %f, bpp: %d\n", 500 mclk, bus, magic, bpp)); 501 PDEBUG5(ErrorF("Total Adapter Bandwidth is %fM\n", total/1000)); 502 503 if (pXGI->VBFlags & CRT2_ENABLE) { 504 total = ((total / 2) > 540000) 505 ? (total - 540000) : (total / 2); 506 } 507 508 return (int)(total / magic); 509} 510 511 512/** 513 * Calculate available memory bandwidth for an XG20 series chip. 514 * 515 * \sa XG20_MemBandWidth 516 */ 517static int XG20_MemBandWidth(ScrnInfoPtr pScrn) 518{ 519 XGIPtr pXGI = XGIPTR(pScrn); 520 const int bus = (pXGI->BusWidth > 128) ? 128 : pXGI->BusWidth; 521 const int mclk = pXGI->MemClock; 522 const int bpp = pScrn->bitsPerPixel; 523 const float magic = 1.44; 524 float total = (mclk * bus) / bpp; 525 526 /* Jong 09/19/2007; support DDRII and double pixel clock */ 527 unsigned long SR39, CR97 ; 528 529 PDEBUG5(ErrorF("mclk: %d, bus: %d, magic: %f, bpp: %d\n", 530 mclk, bus, magic, bpp)); 531 532 total = mclk*bus/bpp; 533 534 /* Jong 04/26/2007; support DDRII and double pixel clock */ 535 /*-------------------------------------------------------*/ 536 inXGIIDXREG(XGISR, 0x39, SR39); 537 inXGIIDXREG(XGICR, 0x97, CR97); 538 539 /* Jong@09082009; modify for XG27 */ 540 if(pXGI->Chipset == PCI_CHIP_XGIXG27) 541 { 542 if (CR97 & 0xC1) 543 total *= 2; 544 } 545 else /* XG20/21 */ 546 { 547 if (CR97 & 0x10) 548 { 549 if (CR97 & 0x01) 550 { 551 total *= 2; 552 } 553 } 554 else 555 { 556 if (SR39 & 0x2) 557 { 558 total *= 2; 559 } 560 } 561 } 562 /*-------------------------------------------------------*/ 563 564 PDEBUG5(ErrorF("Total Adapter Bandwidth is %fM\n", total/1000)); 565 566 return (int)(total / magic); 567} 568 569extern unsigned int g_GammaRed; 570extern unsigned int g_GammaGreen; 571extern unsigned int g_GammaBlue; 572 573void XGIAdjustGamma(ScrnInfoPtr pScrn, unsigned int gammaRed, unsigned int gammaGreen, unsigned int gammaBlue) 574{ 575 XGIPtr pXGI = XGIPTR(pScrn); 576 int num = 255, i; 577 double red = 1.0 / (double)((double)gammaRed / 1000); 578 double green = 1.0 / (double)((double)gammaGreen / 1000); 579 double blue = 1.0 / (double)((double)gammaBlue / 1000); 580 CARD8 GammaRampRed[256], GammaRampGreen[256], GammaRampBlue[256]; 581 582 for(i = 0; i <= num; i++) { 583 GammaRampRed[i] = 584 (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5); 585 586 GammaRampGreen[i] = 587 (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5); 588 589 GammaRampBlue[i] = 590 (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5); 591 } 592 593 /* set gamma ramp to HW */ 594 for(i = 0; i <= 255; i++) { 595 MMIO_OUT32(pXGI->IOBase, 0x8570, 596 (i << 24) | 597 (GammaRampBlue[i] << 16) | 598 (GammaRampGreen[i] << 8) | 599 GammaRampRed[i]); 600 } 601} 602 603void 604XGILoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 605 VisualPtr pVisual) 606{ 607 XGIPtr pXGI = XGIPTR(pScrn); 608 int i, j, index; 609/* unsigned char backup = 0; */ 610 unsigned char SR7; 611 Bool dogamma1 = pXGI->CRT1gamma; 612/* Bool resetxvgamma = FALSE; */ 613 614 if (IS_DUAL_HEAD(pXGI)) { 615 XGIEntPtr pXGIEnt = ENTITY_PRIVATE(pXGI); 616 dogamma1 = pXGIEnt->CRT1gamma; 617 } 618 619 PDEBUG(ErrorF("xgiLoadPalette(%d)\n", numColors)); 620 621 if (!IS_DUAL_HEAD(pXGI) || IS_SECOND_HEAD(pXGI)) { 622 switch(pXGI->CurrentLayout.depth) { 623#ifdef XGIGAMMA 624 case 15: 625 if(dogamma1) { 626 orXGIIDXREG(XGISR, 0x07, 0x04); 627 for(i=0; i<numColors; i++) { 628 index = indices[i]; 629 if(index < 32) { /* Paranoia */ 630 for(j=0; j<8; j++) { 631 outXGIREG(XGICOLIDX, (index * 8) + j); 632 outXGIREG(XGICOLDATA, colors[index].red << (8- pScrn->rgbBits)); 633 outXGIREG(XGICOLDATA, colors[index].green << (8 - pScrn->rgbBits)); 634 outXGIREG(XGICOLDATA, colors[index].blue << (8 - pScrn->rgbBits)); 635 } 636 } 637 } 638 } else { 639 andXGIIDXREG(XGISR, 0x07, ~0x04); 640 } 641 break; 642 case 16: 643 if(dogamma1) { 644 orXGIIDXREG(XGISR, 0x07, 0x04); 645 inXGIIDXREG(XGISR, 0x07, SR7); 646PDEBUG(ErrorF("\ndogamma1 SR7=%x ", SR7)); 647 for(i=0; i<numColors; i++) { 648 index = indices[i]; 649 if(index < 64) { /* Paranoia */ 650 for(j=0; j<4; j++) { 651 outXGIREG(XGICOLIDX, (index * 4) + j); 652 outXGIREG(XGICOLDATA, colors[index/2].red << (8 - pScrn->rgbBits)); 653 outXGIREG(XGICOLDATA, colors[index].green << (8 - pScrn->rgbBits)); 654 outXGIREG(XGICOLDATA, colors[index/2].blue << (8 - pScrn->rgbBits)); 655 } 656 } 657 } 658 } else { 659 andXGIIDXREG(XGISR, 0x07, ~0x04); 660 } 661 break; 662 case 24: 663 if(dogamma1) { 664 orXGIIDXREG(XGISR, 0x07, 0x04); 665 for(i=0; i<numColors; i++) { 666 index = indices[i]; 667 if(index < 256) { /* Paranoia */ 668 outXGIREG(XGICOLIDX, index); 669 outXGIREG(XGICOLDATA, colors[index].red); 670 outXGIREG(XGICOLDATA, colors[index].green); 671 outXGIREG(XGICOLDATA, colors[index].blue); 672 } 673 } 674 } else { 675 andXGIIDXREG(XGISR, 0x07, ~0x04); 676 } 677 break; 678#endif 679 default: 680 if((pScrn->rgbBits == 8) && (dogamma1)) 681 orXGIIDXREG(XGISR, 0x07, 0x04); 682 else 683 andXGIIDXREG(XGISR, 0x07, ~0x04); 684 for(i=0; i<numColors; i++) { 685 index = indices[i]; 686 outXGIREG(XGICOLIDX, index); 687 outXGIREG(XGICOLDATA, colors[index].red >> (8 - pScrn->rgbBits)); 688 outXGIREG(XGICOLDATA, colors[index].green >> (8 - pScrn->rgbBits)); 689 outXGIREG(XGICOLDATA, colors[index].blue >> (8 - pScrn->rgbBits)); 690 } 691 } 692 693 } 694 695 if (!IS_DUAL_HEAD(pXGI) || !IS_SECOND_HEAD(pXGI)) { 696 697 } 698 699 if(pXGI->CurrentLayout.depth != 8) 700 XGIAdjustGamma(pScrn, g_GammaRed, g_GammaGreen, g_GammaBlue); 701} 702 703void 704XGIDACPreInit(ScrnInfoPtr pScrn) 705{ 706 XGIPtr pXGI = XGIPTR(pScrn); 707 708PDEBUG(ErrorF("XGIDACPreInit()\n")); 709 710 pXGI->XGISave = Volari_Save; 711 pXGI->XGIRestore = Volari_Restore; 712 pXGI->SetThreshold = Volari_Threshold; 713 714 pXGI->MaxClock = ((pXGI->Chipset == PCI_CHIP_XGIXG20) || (pXGI->Chipset == PCI_CHIP_XGIXG21) || (pXGI->Chipset == PCI_CHIP_XGIXG27)) 715 ? XG20_MemBandWidth(pScrn) : XG40_MemBandWidth(pScrn); 716} 717 718 719int 720XG40Mclk(XGIPtr pXGI) 721{ 722 int mclk; 723 unsigned char Num, Denum; 724 725 /* Numerator */ 726 /* inXGIIDXREG(0x3c4, 0x28, Num); */ 727 inXGIIDXREG(XGISR, 0x28, Num); 728 mclk = 14318 * ((Num & 0x7f) + 1); 729 730 /* Denumerator */ 731 /* inXGIIDXREG(0x3c4, 0x29, Denum); */ 732 inXGIIDXREG(XGISR, 0x29, Denum); 733 mclk = mclk / ((Denum & 0x1f) + 1); 734 735 /* Divider */ 736 if ((Num & 0x80)!=0) { 737 mclk = mclk * 2; 738 } 739 740 /* Post-Scaler */ 741 mclk /= ((Denum & 0x80) == 0) 742 ? (((Denum & 0x60) >> 5) + 1) 743 : ((((Denum & 0x60) >> 5) + 1) * 2); 744 745 return mclk; 746} 747 748 749static int 750retrace_signals_active(XGIIOADDRESS RelIO) 751{ 752 unsigned char temp; 753 754 /* Make sure the vertical retrace signal is enabled. 755 */ 756 inXGIIDXREG(RelIO + CROFFSET, 0x17, temp); 757 if (!(temp & 0x80)) 758 return 0; 759 760 /* FIXME: Magic offset, what are you? 761 */ 762 inXGIIDXREG(RelIO + SROFFSET, 0x1f, temp); 763 if(temp & 0xc0) 764 return 0; 765 766 return 1; 767} 768 769 770/** 771 * Wait for beginning of next vertical retrace. 772 * 773 * \bugs 774 * The functions \c XGI_WaitBeginRetrace and \c XGI_WaitEndRetrace are 775 * nearly identical. Are both \b really necessary? 776 */ 777void 778XGI_WaitBeginRetrace(XGIIOADDRESS RelIO) 779{ 780 int watchdog; 781 782 if (retrace_signals_active(RelIO)) { 783 /* Wait for the CRTC to leave then re-enter the vertical retrace 784 * period. 785 */ 786 watchdog = 65536; 787 while ((inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE) && --watchdog) 788 /* empty */ ; 789 790 watchdog = 65536; 791 while ((!(inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE)) && --watchdog) 792 /* empty */ ; 793 } 794} 795 796 797/** 798 * Wait for end of next vertical retrace. 799 * 800 * \bugs 801 * The functions \c XGI_WaitBeginRetrace and \c XGI_WaitEndRetrace are 802 * nearly identical. Are both \b really necessary? 803 */ 804void 805XGI_WaitEndRetrace(XGIIOADDRESS RelIO) 806{ 807 int watchdog; 808 809 if (retrace_signals_active(RelIO)) { 810 /* Wait for the CRTC to enter then leave the vertical retrace 811 * period. 812 */ 813 watchdog = 65536; 814 while ((!(inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE)) && --watchdog) 815 /* empty */ ; 816 817 watchdog = 65536; 818 while ((inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE) && --watchdog) 819 /* empty */ ; 820 } 821} 822