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