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