pm3_dac.c revision c35d236e
1/* 2 * Copyright 2000,2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Sven Luther not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Sven Luther makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL SVEN LUTHER BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Authors: Sven Luther, <luther@dpt-info.u-strasbg.fr> 23 * Thomas Witzel, <twitzel@nmr.mgh.harvard.edu> 24 * Alan Hourihane, <alanh@fairlite.demon.co.uk> 25 * 26 * this work is sponsored by Appian Graphics. 27 * 28 */ 29/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_dac.c,v 1.33tsi Exp $ */ 30 31#ifdef HAVE_CONFIG_H 32#include "config.h" 33#endif 34 35#include "xf86.h" 36#include "xf86_OSproc.h" 37 38#include "xf86PciInfo.h" 39#include "xf86Pci.h" 40#include "xf86int10.h" 41 42#include "glint_regs.h" 43#include "pm3_regs.h" 44#include "glint.h" 45 46#define DEBUG 0 47 48#if DEBUG 49# define TRACE_ENTER(str) ErrorF("glint: " str " %d\n",pScrn->scrnIndex) 50# define TRACE_EXIT(str) ErrorF("glint: " str " done\n") 51# define TRACE(str) ErrorF("glint trace: " str "\n") 52#else 53# define TRACE_ENTER(str) 54# define TRACE_EXIT(str) 55# define TRACE(str) 56#endif 57 58int 59Permedia3MemorySizeDetect(ScrnInfoPtr pScrn) 60{ 61 GLINTPtr pGlint = GLINTPTR (pScrn); 62 CARD32 size = 0, temp, temp1, temp2, i; 63 64 /* We can map 64MB, as that's the size of the Permedia3 aperture 65 * regardless of memory configuration */ 66 pGlint->FbMapSize = 64*1024*1024; 67 68 /* Mark as VIDMEM_MMIO to avoid write-combining while detecting memory */ 69 pGlint->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 70 pGlint->PciTag, pGlint->FbAddress, pGlint->FbMapSize); 71 72 if (pGlint->FbBase == NULL) 73 return 0; 74 75 temp = GLINT_READ_REG(PM3MemBypassWriteMask); 76 GLINT_SLOW_WRITE_REG(0xffffffff, PM3MemBypassWriteMask); 77 78 /* The Permedia3 splits up memory, and even replicates it. Grrr. 79 * So that each 32MB appears at offset 0, and offset 32, unless 80 * there's really 64MB attached to the chip. 81 * So, 16MB appears at offset 0, nothing between 16-32, then it re-appears 82 * at offset 32. 83 * This below is to detect the cases of memory combinations 84 */ 85 86 /* Test first 32MB */ 87 for(i=0;i<32;i++) { 88 /* write test pattern */ 89 MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678); 90 mem_barrier(); 91 temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024); 92 /* Let's check for wrapover, write will fail at 16MB boundary */ 93 if (temp1 == (i*0x00345678)) 94 size = i; 95 else 96 break; 97 } 98 99 /* Ok, we're satisfied we've got 32MB, let's test the second lot */ 100 if ((size + 1) == i) { 101 for(i=0;i<32;i++) { 102 /* Clear first 32MB */ 103 MMIO_OUT32(pGlint->FbBase, i*1024*1024, 0); 104 mem_barrier(); 105 } 106 for(i=32;i<64;i++) { 107 /* write test pattern */ 108 MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678); 109 mem_barrier(); 110 temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024); 111 temp2 = MMIO_IN32(pGlint->FbBase, (i-32)*1024*1024); 112 /* Let's check for wrapover */ 113 if ( (temp1 == (i*0x00345678)) && (temp2 == 0) ) 114 size = i; 115 else 116 break; 117 } 118 } 119 120 GLINT_SLOW_WRITE_REG(temp, PM3MemBypassWriteMask); 121 122 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pGlint->FbBase, 123 pGlint->FbMapSize); 124 125 pGlint->FbBase = NULL; 126 pGlint->FbMapSize = 0; 127 128 return ( (size+1) * 1024 ); 129} 130 131static unsigned long 132PM3DAC_CalculateClock 133( 134 unsigned long ReqClock, /* In kHz units */ 135 unsigned long RefClock, /* In kHz units */ 136 unsigned char *prescale, /* ClkPreScale */ 137 unsigned char *feedback, /* ClkFeedBackScale */ 138 unsigned char *postscale /* ClkPostScale */ 139 ) 140{ 141 unsigned long fMinVCO = 2000000; /* min fVCO is 200MHz (in 100Hz units) */ 142 unsigned long fMaxVCO = 6220000; /* max fVCO is 622MHz (in 100Hz units) */ 143 unsigned long fMinINTREF = 10000;/* min fINTREF is 1MHz (in 100Hz units) */ 144 unsigned long fMaxINTREF = 20000;/* max fINTREF is 2MHz (in 100Hz units) */ 145 unsigned long M, N, P; /* M=feedback, N=prescale, P=postscale */ 146 unsigned long fINTREF; 147 unsigned long fVCO; 148 unsigned long ActualClock; 149 long Error; 150 unsigned long LowestError = 1000000; 151 unsigned int bFoundFreq = FALSE; 152 int cInnerLoopIterations = 0; 153 int LoopCount; 154 unsigned long ClosestClock = 0; 155 156 ReqClock*=10; /* convert into 100Hz units */ 157 RefClock*=10; /* convert into 100Hz units */ 158 159 for(P = 0; P <= 5; ++P) 160 { 161 unsigned long fVCOLowest, fVCOHighest; 162 163 /* it is pointless going through the main loop if all values of 164 N produce an fVCO outside the acceptable range */ 165 N = 1; 166 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 167 fVCOLowest = (2 * RefClock * M) / N; 168 N = 255; 169 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 170 fVCOHighest = (2 * RefClock * M) / N; 171 172 if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO) 173 { 174 continue; 175 } 176 177 for(N = 1; N <= 255; ++N, ++cInnerLoopIterations) 178 { 179 fINTREF = RefClock / N; 180 if(fINTREF < fMinINTREF || fINTREF > fMaxINTREF) 181 { 182 if(fINTREF > fMaxINTREF) 183 { 184 /* hopefully we will get into range as the prescale 185 value increases */ 186 continue; 187 } 188 else 189 { 190 /* already below minimum and it will only get worse: 191 move to the next postscale value */ 192 break; 193 } 194 } 195 196 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 197 if(M > 255) 198 { 199 /* M, N & P registers are only 8 bits wide */ 200 break; 201 } 202 203 /* we can expect rounding errors in calculating M, which 204 will always be rounded down. So we will checkout our 205 calculated value of M along with (M+1) */ 206 for(LoopCount = (M == 255) ? 1 : 2; --LoopCount >= 0; ++M) 207 { 208 fVCO = (2 * RefClock * M) / N; 209 if(fVCO >= fMinVCO && fVCO <= fMaxVCO) 210 { 211 ActualClock = fVCO / (1UL << P); 212 Error = ActualClock - ReqClock; 213 if(Error < 0) 214 Error = -Error; 215 if(Error < LowestError) 216 { 217 bFoundFreq = TRUE; 218 LowestError = Error; 219 ClosestClock = ActualClock; 220 *prescale = N; 221 *feedback = M; 222 *postscale = P; 223 if(Error == 0) 224 goto Done; 225 } 226 } 227 } 228 } 229 } 230 231Done: 232 233 if(bFoundFreq) 234 ActualClock = ClosestClock; 235 else 236 ActualClock = 0; 237 238#if 0 239 ErrorF("PM3DAC_CalculateClock: Got prescale=%d, feedback=%d, postscale=%d, WantedClock = %d00 ActualClock = %d00 (Error %d00)\n", 240 *prescale, *feedback, *postscale, ReqClock, ActualClock, LowestError); 241#endif 242 243 return(ActualClock); 244} 245 246static unsigned long 247PM4DAC_CalculateClock 248( 249 unsigned long req_clock, /* In kHz units */ 250 unsigned long ref_clock, /* In kHz units */ 251 unsigned char *param_m, /* ClkPreScale */ 252 unsigned char *param_n, /* ClkFeedBackScale */ 253 unsigned char *param_p /* ClkPostScale */ 254 ) 255{ 256#define INITIALFREQERR 10000 257 258 long fMinVCO = 200000; /* min fVCO is 200MHz (in 10000Hz units) */ 259 long fMaxVCO = 400000; /* max fVCO is 400MHz (in 10000Hz units) */ 260 unsigned long int M, N, P; 261 unsigned long int fVCO; 262 unsigned long int ActualClock; 263 int Error; 264 int LowestError = INITIALFREQERR; 265 short bFoundFreq = FALSE; 266 int cInnerLoopIterations = 0; 267 int LoopCount; 268 269 /* 270 * Actual Equations: 271 * fVCO = (ref_clock * M)/(N+1) 272 * PIXELCLOCK = fVCO/(1<<p) 273 * 200 <= fVCO <= 400 274 * 24 <= N <= 80 275 * 1 <= M <= 15 276 * 0 <= P <= 3 277 * 1Mhz < ref_clock/(N+1) <= 2Mhz - not used 278 * For refclk == 14.318 we have the tighter equations: 279 * 32 <= N <= 80 280 * 3 <= M <= 12 281 * Notes: 282 * The spec says that the PLLs will only do 260Mhz, but I have assumed 300Mhz 'cos 283 * 260Mhz is a crap limit. 284 */ 285 286#define P4RD_PLL_MIN_P 0 287#define P4RD_PLL_MAX_P 3 288#define P4RD_PLL_MIN_M 1 289#define P4RD_PLL_MAX_M 12 290#define P4RD_PLL_MIN_N 24 291#define P4RD_PLL_MAX_N 80 292 293 for(P = P4RD_PLL_MIN_P; P <= P4RD_PLL_MAX_P; ++P) { 294 unsigned long int fVCOLowest, fVCOHighest; 295 296 /* it's pointless going through the main loop if all values of 297 * N produce an fVCO outside the acceptable range */ 298 299 M = P4RD_PLL_MIN_M; 300 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 301 302 fVCOLowest = (ref_clock * N) / (M + 1); 303 304 M = P4RD_PLL_MAX_M; 305 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 306 307 fVCOHighest = (ref_clock * N) / (M + 1); 308 309 if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO) 310 continue; 311 312 for(M = P4RD_PLL_MIN_M; M <= P4RD_PLL_MAX_M; ++M, ++cInnerLoopIterations) 313 { 314 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 315 316 if(N > P4RD_PLL_MAX_N || N < P4RD_PLL_MIN_N) 317 continue; 318 319 /* we can expect rounding errors in calculating M, which will always be rounded down. */ 320 /* So we'll checkout our calculated value of M along with (M+1) */ 321 322 for(LoopCount = (N == P4RD_PLL_MAX_N) ? 1 : 2; --LoopCount >= 0; ++N) 323 { 324 fVCO = (ref_clock * N) / (M + 1); 325 326 if( (fVCO >= fMinVCO) && (fVCO <= fMaxVCO) ) 327 { 328 ActualClock = (fVCO / (1 << P)); 329 330 Error = ActualClock - req_clock; 331 332 if(Error < 0) 333 Error = -Error; 334 335 /* It is desirable that we use the lowest value of M if the*/ 336 /* frequencies are the same.*/ 337 if(Error < LowestError || (Error == LowestError && M < *param_m)) 338 { 339 bFoundFreq = TRUE; 340 LowestError = Error; 341 *param_m = M; 342 *param_n = N; 343 *param_p = P; 344 if(Error == 0) 345 goto Done; 346 } 347 } 348 } 349 } 350 } 351 352Done: 353 if(bFoundFreq) 354 ActualClock = (ref_clock * (*param_n)) / (((*param_m) + 1) * (1 << (*param_p))); 355 else 356 ActualClock = 0; 357 358 return(ActualClock); 359} 360 361void 362Permedia3PreInit(ScrnInfoPtr pScrn) 363{ 364 GLINTPtr pGlint = GLINTPTR(pScrn); 365 CARD32 LocalMemCaps; 366 367 TRACE_ENTER("Permedia3PreInit"); 368 369 if (IS_J2000) { 370 unsigned char m,n,p; 371 372 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 373 GLINT_SLOW_WRITE_REG(GCSRSecondaryGLINTMapEn, GCSRAperture); 374 375 /* Memory timings for the Appian J2000 board. 376 * This is needed for the second head which is left un-initialized 377 * by the bios, thus freezing the machine. */ 378 GLINT_SLOW_WRITE_REG(0x02e311B8, PM3LocalMemCaps); 379 GLINT_SLOW_WRITE_REG(0x07424905, PM3LocalMemTimings); 380 GLINT_SLOW_WRITE_REG(0x0c000003, PM3LocalMemControl); 381 GLINT_SLOW_WRITE_REG(0x00000061, PM3LocalMemRefresh); 382 GLINT_SLOW_WRITE_REG(0x00000000, PM3LocalMemPowerDown); 383 384 /* Let's program the K, M and S Clocks to the same values as the bios 385 * does for first head : 386 * - KClk and MClk are 105Mhz. 387 * - S Clock is set to PClk. 388 * Note 1 : pGlint->RefClock is not set yet, so use 14318 instead. 389 * Note 2 : KClk gets internally halved, so we need to double it. 390 */ 391 (void) PM3DAC_CalculateClock(2*105000, 14318, &m,&n,&p); 392 Permedia2vOutIndReg(pScrn, PM3RD_KClkPreScale, 0x00, m); 393 Permedia2vOutIndReg(pScrn, PM3RD_KClkFeedbackScale, 0x00, n); 394 Permedia2vOutIndReg(pScrn, PM3RD_KClkPostScale, 0x00, p); 395 Permedia2vOutIndReg(pScrn, PM3RD_KClkControl, 0x00, 396 PM3RD_KClkControl_STATE_RUN | 397 PM3RD_KClkControl_SOURCE_PLL | 398 PM3RD_KClkControl_ENABLE); 399 Permedia2vOutIndReg(pScrn, PM3RD_MClkControl, 0x00, 400 PM3RD_MClkControl_STATE_RUN | 401 PM3RD_MClkControl_SOURCE_KCLK | 402 PM3RD_MClkControl_ENABLE); 403 Permedia2vOutIndReg(pScrn, PM3RD_SClkControl, 0x00, 404 PM3RD_SClkControl_STATE_RUN | 405 PM3RD_SClkControl_SOURCE_PCLK | 406 PM3RD_SClkControl_ENABLE); 407 } 408 409#if defined(__alpha__) 410 /* 411 * On Alpha, we have to "int10" secondary VX1 cards early; 412 * otherwise, some information taken from registers, like 413 * memory size, is incorrect. 414 */ 415 if (!xf86IsPrimaryPci(pGlint->PciInfo)) { 416 if ( IS_QVX1 ) { 417 418 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 419 "VX1 secondary enabling VGA before int10\n"); 420 421 /* Enable VGA on the current card. */ 422 pciWriteByte( pGlint->PciTag, 0xf8, 0 ); 423 pciWriteByte( pGlint->PciTag, 0xf4, 0 ); 424 pciWriteByte( pGlint->PciTag, 0xfc, 0 ); 425 426 /* The card we are on should be VGA-enabled now, so run int10. */ 427 if (xf86LoadSubModule(pScrn, "int10")) { 428 xf86Int10InfoPtr pInt; 429 430 xf86LoaderReqSymLists(GLINTint10Symbols, NULL); 431 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); 432 pInt = xf86InitInt10(pGlint->pEnt->index); 433 xf86FreeInt10(pInt); 434 } 435 436 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 437 "VX1 secondary disabling VGA after int10\n"); 438 439 /* Finally, disable VGA on the current card. */ 440 pciWriteByte( pGlint->PciTag, 0xf8, 0x70 ); 441 pciWriteByte( pGlint->PciTag, 0xf4, 0x01 ); 442 pciWriteByte( pGlint->PciTag, 0xfc, 0x00 ); 443 } 444 } 445#endif /* __alpha__ */ 446 447 /* If we have SDRAM instead of SGRAM, we have to do some things 448 differently in the FillRectSolid code. */ 449 LocalMemCaps = GLINT_READ_REG(PM3LocalMemCaps); 450 pGlint->PM3_UsingSGRAM = !(LocalMemCaps & PM3LocalMemCaps_NoWriteMask); 451 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s memory\n", 452 pGlint->PM3_UsingSGRAM ? "SGRAM" : "SDRAM"); 453 454 TRACE_EXIT("Permedia3PreInit"); 455} 456 457Bool 458Permedia3Init(ScrnInfoPtr pScrn, DisplayModePtr mode, GLINTRegPtr pReg) 459{ 460 GLINTPtr pGlint = GLINTPTR(pScrn); 461 CARD32 temp1, temp2, temp3, temp4; 462 463 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 464 STOREREG(GCSRAperture, GCSRSecondaryGLINTMapEn); 465 } 466 467 if (pGlint->MultiAperture) { 468 STOREREG(GMultGLINTAperture, pGlint->realWidth); 469 STOREREG(GMultGLINT1, 470 pGlint->MultiPciInfo[0]->memBase[2] & 0xFF800000); 471 STOREREG(GMultGLINT2, 472 pGlint->MultiPciInfo[1]->memBase[2] & 0xFF800000); 473 } 474 475 STOREREG(PM3MemBypassWriteMask, 0xffffffff); 476 STOREREG(Aperture0, 0x00000000); 477 STOREREG(Aperture1, 0x00000000); 478 479 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 480 STOREREG(DFIFODis, 0x00000001); 481 482 STOREREG(FIFODis, 0x00000007); 483 484 temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay; 485 temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay; 486 temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; 487 temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 488 489 STOREREG(PMHTotal, Shiftbpp(pScrn, mode->CrtcHTotal - 1)); 490 STOREREG(PMHsEnd, Shiftbpp(pScrn, temp1 + temp3)); 491 STOREREG(PMHsStart, Shiftbpp(pScrn, temp1)); 492 STOREREG(PMHbEnd, Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay)); 493 STOREREG(PMHgEnd, Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay)); 494 STOREREG(PMScreenStride, Shiftbpp(pScrn, pScrn->displayWidth)); 495 496 STOREREG(PMVTotal, mode->CrtcVTotal - 1); 497 STOREREG(PMVsEnd, temp2 + temp4 - 1); 498 STOREREG(PMVsStart, temp2 - 1); 499 STOREREG(PMVbEnd, mode->CrtcVTotal - mode->CrtcVDisplay); 500 501 switch (pScrn->bitsPerPixel) 502 { 503 case 8: 504 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT); 505 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT); 506 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (0 << 19)); 507 break; 508 case 16: 509#if X_BYTE_ORDER != X_BIG_ENDIAN 510 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT); 511 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT); 512#else 513 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT | 514 PM3ByApertureMode_BYTESWAP_BADC); 515 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT | 516 PM3ByApertureMode_BYTESWAP_BADC); 517#endif 518 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (1 << 19)); 519 break; 520 case 32: 521#if X_BYTE_ORDER != X_BIG_ENDIAN 522 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT); 523 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT); 524#else 525 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT | 526 PM3ByApertureMode_BYTESWAP_DCBA); 527 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT | 528 PM3ByApertureMode_BYTESWAP_DCBA); 529#endif 530 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (2 << 19)); 531 break; 532 } 533 534 STOREREG(VClkCtl, GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC); 535 STOREREG(PMScreenBase, 0x00000000); 536 STOREREG(ChipConfig, GLINT_READ_REG(ChipConfig) & 0xFFFFFFFD); 537 538 { 539 /* Get the programmable clock values */ 540 unsigned char m,n,p; 541 542 /* Let's program the dot clock */ 543 switch (pGlint->Chipset) { 544 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA4: 545 case PCI_VENDOR_3DLABS_CHIP_R4: 546 (void) PM4DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p); 547 break; 548 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA3: 549 (void) PM3DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p); 550 break; 551 case PCI_VENDOR_3DLABS_CHIP_GAMMA: 552 switch (pGlint->MultiChip) { 553 case PCI_CHIP_PERMEDIA3: 554 (void) PM3DAC_CalculateClock(mode->Clock, 555 pGlint->RefClock, &m,&n,&p); 556 break; 557 case PCI_CHIP_R4: 558 (void) PM4DAC_CalculateClock(mode->Clock, 559 pGlint->RefClock, &m,&n,&p); 560 break; 561 } 562 break; 563 } 564 STOREDAC(PM3RD_DClk0PreScale, m); 565 STOREDAC(PM3RD_DClk0FeedbackScale, n); 566 STOREDAC(PM3RD_DClk0PostScale, p); 567 } 568 569 temp1 = 0; 570 temp2 = 0; 571 temp3 = 0; 572 573 if (pGlint->UseFlatPanel) { 574 temp2 |= PM3RD_DACControl_BLANK_PEDESTAL_ENABLE; 575 temp3 |= PM3RD_MiscControl_VSB_OUTPUT_ENABLE; 576 STOREREG(VSConfiguration, 0x06); 577 STOREREG(VSBBase, 1<<14); 578 } 579 580 if (mode->Flags & V_PHSYNC) temp1 |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; 581 if (mode->Flags & V_PVSYNC) temp1 |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; 582 583 STOREREG(PM2VDACRDIndexControl, 0x00); 584 STOREDAC(PM2VDACRDSyncControl, temp1); 585 STOREDAC(PM2VDACRDDACControl, temp2); 586 587 if (pScrn->rgbBits == 8) 588 temp3 |= 0x01; /* 8bit DAC */ 589 590 switch (pScrn->bitsPerPixel) 591 { 592 case 8: 593 STOREDAC(PM2VDACRDPixelSize, 0x00); 594 STOREDAC(PM2VDACRDColorFormat, 0x2E); 595 break; 596 case 16: 597 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 598 STOREDAC(PM2VDACRDPixelSize, 0x01); 599 if (pScrn->depth == 15) { 600 STOREDAC(PM2VDACRDColorFormat, 0x61); 601 } else { 602 STOREDAC(PM2VDACRDColorFormat, 0x70); 603 } 604 break; 605 case 24: 606 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 607 STOREDAC(PM2VDACRDPixelSize, 0x04); 608 STOREDAC(PM2VDACRDColorFormat, 0x20); 609 break; 610 case 32: 611 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 612 if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) { 613 temp3 |= 0x18; 614 STOREDAC(PM2VDACRDOverlayKey, pScrn->colorKey); 615 } 616 STOREDAC(PM2VDACRDPixelSize, 0x02); 617 STOREDAC(PM2VDACRDColorFormat, 0x20); 618 break; 619 } 620 STOREDAC(PM2VDACRDMiscControl, temp3); 621 622 STOREREG(PM3FifoControl, 0x905); /* Lower the default fifo threshold */ 623 624 return(TRUE); 625} 626 627void 628Permedia3Save(ScrnInfoPtr pScrn, GLINTRegPtr pReg) 629{ 630 GLINTPtr pGlint = GLINTPTR(pScrn); 631 int i; 632 633 /* We can't rely on the vgahw layer copying the font information 634 * back properly, due to problems with MMIO access to VGA space 635 * so we memcpy the information using the slow routines */ 636 xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536); 637 638 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 639 SAVEREG(GCSRAperture); 640 } 641 642 if (pGlint->MultiAperture) { 643 SAVEREG(GMultGLINTAperture); 644 SAVEREG(GMultGLINT1); 645 SAVEREG(GMultGLINT2); 646 } 647 648 /* Permedia 3 memory Timings */ 649 SAVEREG(PM3MemBypassWriteMask); 650 SAVEREG(PM3ByAperture1Mode); 651 SAVEREG(PM3ByAperture2Mode); 652 SAVEREG(ChipConfig); 653 SAVEREG(Aperture0); 654 SAVEREG(Aperture1); 655 SAVEREG(PM3FifoControl); 656 657 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 658 SAVEREG(DFIFODis); 659 SAVEREG(FIFODis); 660 SAVEREG(PMHTotal); 661 SAVEREG(PMHbEnd); 662 SAVEREG(PMHgEnd); 663 SAVEREG(PMScreenStride); 664 SAVEREG(PMHsStart); 665 SAVEREG(PMHsEnd); 666 SAVEREG(PMVTotal); 667 SAVEREG(PMVbEnd); 668 SAVEREG(PMVsStart); 669 SAVEREG(PMVsEnd); 670 SAVEREG(PMScreenBase); 671 SAVEREG(PMVideoControl); 672 SAVEREG(VClkCtl); 673 if (pGlint->UseFlatPanel) { 674 SAVEREG(VSConfiguration); 675 SAVEREG(VSBBase); 676 } 677 678 for (i=0;i<768;i++) { 679 Permedia2ReadAddress(pScrn, i); 680 pReg->cmap[i] = Permedia2ReadData(pScrn); 681 } 682 683 SAVEREG(PM2VDACRDIndexControl); 684 P2VIN(PM2VDACRDOverlayKey); 685 P2VIN(PM2VDACRDSyncControl); 686 P2VIN(PM2VDACRDMiscControl); 687 P2VIN(PM2VDACRDDACControl); 688 P2VIN(PM2VDACRDPixelSize); 689 P2VIN(PM2VDACRDColorFormat); 690 P2VIN(PM2VDACRDDClk0PreScale); 691 P2VIN(PM2VDACRDDClk0FeedbackScale); 692 P2VIN(PM2VDACRDDClk0PostScale); 693} 694 695void 696Permedia3Restore(ScrnInfoPtr pScrn, GLINTRegPtr pReg) 697{ 698 GLINTPtr pGlint = GLINTPTR(pScrn); 699 CARD32 temp; 700 int i; 701 702 /* We can't rely on the vgahw layer copying the font information 703 * back properly, due to problems with MMIO access to VGA space 704 * so we memcpy the information using the slow routines */ 705 if (pGlint->STATE) 706 xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536); 707 708 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 709 RESTOREREG(GCSRAperture); 710 } 711 712 if (pGlint->MultiAperture) { 713 RESTOREREG(GMultGLINTAperture); 714 RESTOREREG(GMultGLINT1); 715 RESTOREREG(GMultGLINT2); 716 } 717 718 /* Permedia 3 memory Timings */ 719 RESTOREREG(PM3MemBypassWriteMask); 720 RESTOREREG(PM3ByAperture1Mode); 721 RESTOREREG(PM3ByAperture2Mode); 722 RESTOREREG(ChipConfig); 723 RESTOREREG(Aperture0); 724 RESTOREREG(Aperture1); 725 RESTOREREG(PM3FifoControl); 726 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 727 RESTOREREG(DFIFODis); 728 RESTOREREG(FIFODis); 729 RESTOREREG(PMVideoControl); 730 RESTOREREG(PMHbEnd); 731 RESTOREREG(PMHgEnd); 732 RESTOREREG(PMScreenBase); 733 RESTOREREG(VClkCtl); 734 RESTOREREG(PMScreenStride); 735 RESTOREREG(PMHTotal); 736 RESTOREREG(PMHsStart); 737 RESTOREREG(PMHsEnd); 738 RESTOREREG(PMVTotal); 739 RESTOREREG(PMVbEnd); 740 RESTOREREG(PMVsStart); 741 RESTOREREG(PMVsEnd); 742 743 if (pGlint->UseFlatPanel) { 744 RESTOREREG(VSConfiguration); 745 RESTOREREG(VSBBase); 746 } 747 748 RESTOREREG(PM2VDACRDIndexControl); 749 P2VOUT(PM2VDACRDOverlayKey); 750 P2VOUT(PM2VDACRDSyncControl); 751 P2VOUT(PM2VDACRDMiscControl); 752 P2VOUT(PM2VDACRDDACControl); 753 P2VOUT(PM2VDACRDPixelSize); 754 P2VOUT(PM2VDACRDColorFormat); 755 756 for (i=0;i<768;i++) { 757 Permedia2WriteAddress(pScrn, i); 758 Permedia2WriteData(pScrn, pReg->cmap[i]); 759 } 760 761 temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC; 762 P2VOUT(PM2VDACRDDClk0PreScale); 763 P2VOUT(PM2VDACRDDClk0FeedbackScale); 764 P2VOUT(PM2VDACRDDClk0PostScale); 765 Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03); 766} 767 768void Permedia3LoadPalette( 769 ScrnInfoPtr pScrn, 770 int numColors, 771 int *indices, 772 LOCO *colors, 773 VisualPtr pVisual 774){ 775#if 0 776 GLINTPtr pGlint = GLINTPTR(pScrn); 777#endif 778 int i, index, shift = 0, j, repeat = 1; 779 780 if (pScrn->depth == 15) { 781 repeat = 8; 782 shift = 3; 783 } 784 785 for(i = 0; i < numColors; i++) { 786 index = indices[i]; 787 for (j = 0; j < repeat; j++) { 788 Permedia2WriteAddress(pScrn, (index << shift)+j); 789 Permedia2WriteData(pScrn, colors[index].red); 790 Permedia2WriteData(pScrn, colors[index].green); 791 Permedia2WriteData(pScrn, colors[index].blue); 792 } 793#if 0 794 GLINT_SLOW_WRITE_REG(index, PM3LUTIndex); 795 GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) | 796 ((colors[index].green & 0xFF) << 8) | 797 ((colors[index].blue & 0xFF) << 16), 798 PM3LUTData); 799#endif 800 } 801} 802 803/* special one for 565 mode */ 804void Permedia3LoadPalette16( 805 ScrnInfoPtr pScrn, 806 int numColors, 807 int *indices, 808 LOCO *colors, 809 VisualPtr pVisual 810){ 811#if 0 812 GLINTPtr pGlint = GLINTPTR(pScrn); 813#endif 814 int i, index, j; 815 816 for(i = 0; i < numColors; i++) { 817 index = indices[i]; 818 for (j = 0; j < 4; j++) { 819 Permedia2WriteAddress(pScrn, (index << 2)+j); 820 Permedia2WriteData(pScrn, colors[index >> 1].red); 821 Permedia2WriteData(pScrn, colors[index].green); 822 Permedia2WriteData(pScrn, colors[index >> 1].blue); 823 } 824#if 0 825 GLINT_SLOW_WRITE_REG(index, PM3LUTIndex); 826 GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) | 827 ((colors[index].green & 0xFF) << 8) | 828 ((colors[index].blue & 0xFF) << 16), 829 PM3LUTData); 830#endif 831 832 if(index <= 31) { 833 for (j = 0; j < 4; j++) { 834 Permedia2WriteAddress(pScrn, (index << 3)+j); 835 Permedia2WriteData(pScrn, colors[index].red); 836 Permedia2WriteData(pScrn, colors[(index << 1) + 1].green); 837 Permedia2WriteData(pScrn, colors[index].blue); 838 } 839 } 840 } 841} 842