pm2v_dac.c revision c35d236e
1/* 2 * Copyright 1997-2001 by Alan Hourihane <alanh@fairlite.demon.co.uk> 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 Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane 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 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE 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: Alan Hourihane, <alanh@fairlite.demon.co.uk> 23 * Dirk Hohndel, <hohndel@suse.de> 24 * Stefan Dirsch, <sndirsch@suse.de> 25 * Helmut Fahrion, <hf@suse.de> 26 * 27 * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and 28 * Siemens Nixdorf Informationssysteme 29 */ 30/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm2v_dac.c,v 1.29tsi Exp $ */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include "xf86.h" 37#include "xf86_OSproc.h" 38 39#include "xf86PciInfo.h" 40#include "xf86Pci.h" 41 42#include "glint_regs.h" 43#include "glint.h" 44 45static unsigned long 46PM2VDAC_CalculateClock 47( 48 unsigned long reqclock, /* In kHz units */ 49 unsigned long refclock, /* In kHz units */ 50 unsigned char *prescale, /* ClkPreScale */ 51 unsigned char *feedback, /* ClkFeedBackScale */ 52 unsigned char *postscale /* ClkPostScale */ 53 ) 54{ 55 int f, pre, post; 56 unsigned long freq; 57 long freqerr = 1000; 58 unsigned long actualclock = 0; 59 unsigned char divide[5] = { 1, 2, 4, 8, 16 }; 60 61 for (f=1;f<256;f++) { 62 for (pre=1;pre<256;pre++) { 63 for (post=0;post<2;post++) { 64 freq = ((refclock * f) / (pre * (1 << divide[post]))); 65 if ((reqclock > freq - freqerr)&&(reqclock < freq + freqerr)){ 66 freqerr = (reqclock > freq) ? 67 reqclock - freq : freq - reqclock; 68 *feedback = f; 69 *prescale = pre; 70 *postscale = post; 71 actualclock = freq; 72 } 73 } 74 } 75 } 76 77 return(actualclock); 78} 79 80static void 81Permedia2VPreInitSecondary(ScrnInfoPtr pScrn) 82{ 83 GLINTPtr pGlint = GLINTPTR(pScrn); 84 85 /* disable MCLK */ 86 Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 0); 87 88 /* boot new mclk values */ 89 Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPreScale, 0x00, 0x09); 90 Permedia2vOutIndReg(pScrn, PM2VDACRDMClkFeedbackScale, 0x00, 0x58); 91 Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPostScale, 0x00, 0x01); 92 93 /* re-enable MCLK */ 94 Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 1); 95 96 /* spin until locked MCLK */ 97 while ( (Permedia2vInIndReg(pScrn, PM2VDACRDMClkControl) & 0x2) == 0); 98 99 /* Now re-boot the SGRAM's */ 100 GLINT_SLOW_WRITE_REG(0xe6002021,PMMemConfig); 101 GLINT_SLOW_WRITE_REG(0x00000020,PMBootAddress); 102} 103 104void 105Permedia2VPreInit(ScrnInfoPtr pScrn) 106{ 107 GLINTPtr pGlint = GLINTPTR(pScrn); 108 109 if (IS_JPRO) { 110 /* Appian Jeronimo Pro 4x8mb (pm2v version) */ 111 /* BIOS doesn't initialize the secondary heads, so we need to */ 112 113 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 114 "Appian Jeronimo Pro 4x8mb board detected and initialized.\n"); 115 116 Permedia2VPreInitSecondary(pScrn); 117 } 118 119#if defined(__alpha__) 120 /* 121 * On Alpha, we have to init secondary PM2V cards, since 122 * int10 cannot be run on the OEMed cards with VGA disable 123 * jumpers. 124 */ 125 if (!xf86IsPrimaryPci(pGlint->PciInfo)) { 126 if ( IS_QPM2V ) { 127 128 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 129 "PM2V secondary: initializing\n"); 130 Permedia2VPreInitSecondary(pScrn); 131 } 132 } 133#endif /* __alpha__ */ 134} 135 136Bool 137Permedia2VInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 138{ 139 GLINTPtr pGlint = GLINTPTR(pScrn); 140 GLINTRegPtr pReg = &pGlint->ModeReg[0]; 141 CARD32 temp1, temp2, temp3, temp4; 142 143 temp1 = 0; 144 temp2 = 0; 145#if X_BYTE_ORDER == X_BIG_ENDIAN 146 switch (pGlint->HwBpp) { 147 case 8: 148 case 24: 149 temp1 = 0x00; 150 temp2 = 0x00; 151 break; 152 153 case 15: 154 case 16: 155 temp1 = 0x02; 156 temp2 = 0x02; 157 break; 158 159 case 32: 160 temp1 = 0x01; 161 temp2 = 0x01; 162 break; 163 default: 164 break; 165 }; 166#endif /* BIG_ENDIAN */ 167 168 pReg->glintRegs[Aperture0 >> 3] = temp1; 169 pReg->glintRegs[Aperture1 >> 3] = temp2; 170 171 pReg->glintRegs[PMFramebufferWriteMask >> 3] = 0xFFFFFFFF; 172 pReg->glintRegs[PMBypassWriteMask >> 3] = 0xFFFFFFFF; 173 174 pReg->glintRegs[DFIFODis >> 3] = 0; 175 pReg->glintRegs[FIFODis >> 3] = 1; 176 177 if (pGlint->UseBlockWrite) 178 pReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig) | 1<<21; 179 180 temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay; 181 temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay; 182 temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; 183 temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 184 185 pReg->glintRegs[PMHTotal >> 3] = Shiftbpp(pScrn,mode->CrtcHTotal); 186 pReg->glintRegs[PMHsEnd >> 3] = Shiftbpp(pScrn, temp1 + temp3); 187 pReg->glintRegs[PMHsStart >> 3] = Shiftbpp(pScrn, temp1); 188 pReg->glintRegs[PMHbEnd >> 3] = 189 Shiftbpp(pScrn,mode->CrtcHTotal-mode->CrtcHDisplay); 190 pReg->glintRegs[PMScreenStride >> 3] = 191 Shiftbpp(pScrn,pScrn->displayWidth>>1); 192 193 pReg->glintRegs[PMVTotal >> 3] = mode->CrtcVTotal; 194 pReg->glintRegs[PMVsEnd >> 3] = temp2 + temp4; 195 pReg->glintRegs[PMVsStart >> 3] = temp2; 196 pReg->glintRegs[PMVbEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay; 197 198 /* The hw cursor needs /VSYNC to recognize vert retrace. We'll stick 199 both sync lines to active low here and if needed invert them 200 using the RAMDAC's RDSyncControl below. */ 201 pReg->glintRegs[PMVideoControl >> 3] = 202 (1 << 5) | (1 << 3) | 1; 203 204 /* We stick the RAMDAC into 64bit mode */ 205 /* And reduce the horizontal timings and clock by half */ 206 pReg->glintRegs[PMVideoControl >> 3] |= 1<<16; 207 pReg->glintRegs[PMHTotal >> 3] >>= 1; 208 pReg->glintRegs[PMHsEnd >> 3] >>= 1; 209 pReg->glintRegs[PMHsStart >> 3] >>= 1; 210 pReg->glintRegs[PMHbEnd >> 3] >>= 1; 211 212 pReg->glintRegs[VClkCtl >> 3] = (GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC); 213 pReg->glintRegs[PMScreenBase >> 3] = 0; 214 pReg->glintRegs[PMHTotal >> 3] -= 1; 215 pReg->glintRegs[PMHsStart >> 3] -= 1; /* PMHsStart */ 216 pReg->glintRegs[PMVTotal >> 3] -= 1; /* PMVTotal */ 217 218 pReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig) & 0xFFFFFFDD; 219 pReg->DacRegs[PM2VDACRDDACControl] = 0x00; 220 221 { 222 /* Get the programmable clock values */ 223 unsigned char m,n,p; 224 225 (void) PM2VDAC_CalculateClock(mode->Clock/2,pGlint->RefClock, 226 &m,&n,&p); 227 pReg->DacRegs[PM2VDACRDDClk0PreScale] = m; 228 pReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = n; 229 pReg->DacRegs[PM2VDACRDDClk0PostScale] = p; 230 } 231 232 pReg->glintRegs[PM2VDACRDIndexControl >> 3] = 0x00; 233 234 if (pScrn->rgbBits == 8) 235 pReg->DacRegs[PM2VDACRDMiscControl] = 0x01; /* 8bit DAC */ 236 else 237 pReg->DacRegs[PM2VDACRDMiscControl] = 0x00; /* 6bit DAC */ 238 239 pReg->DacRegs[PM2VDACRDSyncControl] = 0x00; 240 if (mode->Flags & V_PHSYNC) 241 pReg->DacRegs[PM2VDACRDSyncControl] |= 0x01; /* invert hsync */ 242 if (mode->Flags & V_PVSYNC) 243 pReg->DacRegs[PM2VDACRDSyncControl] |= 0x08; /* invert vsync */ 244 245 switch (pScrn->bitsPerPixel) 246 { 247 case 8: 248 pReg->DacRegs[PM2VDACRDPixelSize] = 0x00; 249 pReg->DacRegs[PM2VDACRDColorFormat] = 0x2E; 250 break; 251 case 16: 252 pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08; 253 pReg->DacRegs[PM2VDACRDPixelSize] = 0x01; 254 if (pScrn->depth == 15) 255 pReg->DacRegs[PM2VDACRDColorFormat] = 0x61; 256 else 257 pReg->DacRegs[PM2VDACRDColorFormat] = 0x70; 258 break; 259 case 24: 260 pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08; 261 pReg->DacRegs[PM2VDACRDPixelSize] = 0x04; 262 pReg->DacRegs[PM2VDACRDColorFormat] = 0x60; 263 break; 264 case 32: 265 pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08; 266 pReg->DacRegs[PM2VDACRDPixelSize] = 0x02; 267 pReg->DacRegs[PM2VDACRDColorFormat] = 0x20; 268 if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) { 269 pReg->DacRegs[PM2VDACRDMiscControl] |= 0x18; 270 pReg->DacRegs[PM2VDACRDOverlayKey] = pScrn->colorKey; 271 } 272 break; 273 } 274 275 return(TRUE); 276} 277 278void 279Permedia2VSave(ScrnInfoPtr pScrn, GLINTRegPtr glintReg) 280{ 281 GLINTPtr pGlint = GLINTPTR(pScrn); 282 int i; 283 284 /* We can't rely on the vgahw layer copying the font information 285 * back properly, due to problems with MMIO access to VGA space 286 * so we memcpy the information */ 287 memcpy((CARD8*)pGlint->VGAdata,(CARD8*)pGlint->FbBase, 65536); 288 289 glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig); 290 glintReg->glintRegs[Aperture0 >> 3] = GLINT_READ_REG(Aperture0); 291 glintReg->glintRegs[Aperture1 >> 3] = GLINT_READ_REG(Aperture1); 292 glintReg->glintRegs[PMFramebufferWriteMask >> 3] = 293 GLINT_READ_REG(PMFramebufferWriteMask); 294 glintReg->glintRegs[PMBypassWriteMask >> 3] = 295 GLINT_READ_REG(PMBypassWriteMask); 296 glintReg->glintRegs[DFIFODis >> 3] = GLINT_READ_REG(DFIFODis); 297 glintReg->glintRegs[FIFODis >> 3] = GLINT_READ_REG(FIFODis); 298 /* We only muck about with PMMemConfig, if user wants to */ 299 if (pGlint->UseBlockWrite) 300 glintReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig); 301 glintReg->glintRegs[PMHTotal >> 3] = GLINT_READ_REG(PMHTotal); 302 glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHbEnd); 303 glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHgEnd); 304 glintReg->glintRegs[PMScreenStride >> 3] = GLINT_READ_REG(PMScreenStride); 305 glintReg->glintRegs[PMHsStart >> 3] = GLINT_READ_REG(PMHsStart); 306 glintReg->glintRegs[PMHsEnd >> 3] = GLINT_READ_REG(PMHsEnd); 307 glintReg->glintRegs[PMVTotal >> 3] = GLINT_READ_REG(PMVTotal); 308 glintReg->glintRegs[PMVbEnd >> 3] = GLINT_READ_REG(PMVbEnd); 309 glintReg->glintRegs[PMVsStart >> 3] = GLINT_READ_REG(PMVsStart); 310 glintReg->glintRegs[PMVsEnd >> 3] = GLINT_READ_REG(PMVsEnd); 311 glintReg->glintRegs[PMScreenBase >> 3] = GLINT_READ_REG(PMScreenBase); 312 glintReg->glintRegs[PMVideoControl >> 3] = GLINT_READ_REG(PMVideoControl); 313 glintReg->glintRegs[VClkCtl >> 3] = GLINT_READ_REG(VClkCtl); 314 315 for (i=0;i<768;i++) { 316 Permedia2ReadAddress(pScrn, i); 317 glintReg->cmap[i] = Permedia2ReadData(pScrn); 318 } 319 320 glintReg->glintRegs[PM2VDACRDIndexControl >> 3] = 321 GLINT_READ_REG(PM2VDACRDIndexControl); 322 glintReg->DacRegs[PM2VDACRDOverlayKey] = 323 Permedia2vInIndReg(pScrn, PM2VDACRDOverlayKey); 324 glintReg->DacRegs[PM2VDACRDSyncControl] = 325 Permedia2vInIndReg(pScrn, PM2VDACRDSyncControl); 326 glintReg->DacRegs[PM2VDACRDMiscControl] = 327 Permedia2vInIndReg(pScrn, PM2VDACRDMiscControl); 328 glintReg->DacRegs[PM2VDACRDDACControl] = 329 Permedia2vInIndReg(pScrn, PM2VDACRDDACControl); 330 glintReg->DacRegs[PM2VDACRDPixelSize] = 331 Permedia2vInIndReg(pScrn, PM2VDACRDPixelSize); 332 glintReg->DacRegs[PM2VDACRDColorFormat] = 333 Permedia2vInIndReg(pScrn, PM2VDACRDColorFormat); 334 335 glintReg->DacRegs[PM2VDACRDDClk0PreScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PreScale); 336 glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0FeedbackScale); 337 glintReg->DacRegs[PM2VDACRDDClk0PostScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PostScale); 338} 339 340void 341Permedia2VRestore(ScrnInfoPtr pScrn, GLINTRegPtr glintReg) 342{ 343 GLINTPtr pGlint = GLINTPTR(pScrn); 344 CARD32 temp; 345 int i; 346 347 /* We can't rely on the vgahw layer copying the font information 348 * back properly, due to problems with MMIO access to VGA space 349 * so we memcpy the information */ 350 if (pGlint->STATE) 351 memcpy((CARD8*)pGlint->FbBase,(CARD8*)pGlint->VGAdata, 65536); 352 353 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[ChipConfig >> 3], ChipConfig); 354 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture0 >> 3], Aperture0); 355 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture1 >> 3], Aperture1); 356 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMFramebufferWriteMask >> 3], 357 PMFramebufferWriteMask); 358 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMBypassWriteMask >> 3], 359 PMBypassWriteMask); 360 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[DFIFODis >> 3], DFIFODis); 361 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[FIFODis >> 3], FIFODis); 362 /* We only muck about with PMMemConfig, if user wants to */ 363 if (pGlint->UseBlockWrite) 364 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMMemConfig >> 3],PMMemConfig); 365 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVideoControl >> 3], 366 PMVideoControl); 367 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHgEnd); 368 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenBase >> 3], PMScreenBase); 369 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[VClkCtl >> 3], VClkCtl); 370 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenStride >> 3], 371 PMScreenStride); 372 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHTotal >> 3], PMHTotal); 373 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHbEnd); 374 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsStart >> 3], PMHsStart); 375 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsEnd >> 3], PMHsEnd); 376 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVTotal >> 3], PMVTotal); 377 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVbEnd >> 3], PMVbEnd); 378 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsStart >> 3], PMVsStart); 379 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsEnd >> 3], PMVsEnd); 380 381 GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PM2VDACRDIndexControl >> 3], 382 PM2VDACRDIndexControl); 383 Permedia2vOutIndReg(pScrn, PM2VDACRDOverlayKey, 0x00, 384 glintReg->DacRegs[PM2VDACRDOverlayKey]); 385 Permedia2vOutIndReg(pScrn, PM2VDACRDSyncControl, 0x00, 386 glintReg->DacRegs[PM2VDACRDSyncControl]); 387 Permedia2vOutIndReg(pScrn, PM2VDACRDMiscControl, 0x00, 388 glintReg->DacRegs[PM2VDACRDMiscControl]); 389 Permedia2vOutIndReg(pScrn, PM2VDACRDDACControl, 0x00, 390 glintReg->DacRegs[PM2VDACRDDACControl]); 391 Permedia2vOutIndReg(pScrn, PM2VDACRDPixelSize, 0x00, 392 glintReg->DacRegs[PM2VDACRDPixelSize]); 393 Permedia2vOutIndReg(pScrn, PM2VDACRDColorFormat, 0x00, 394 glintReg->DacRegs[PM2VDACRDColorFormat]); 395 396 for (i=0;i<768;i++) { 397 Permedia2WriteAddress(pScrn, i); 398 Permedia2WriteData(pScrn, glintReg->cmap[i]); 399 } 400 401 temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC; 402 Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PreScale, 0x00, 403 glintReg->DacRegs[PM2VDACRDDClk0PreScale]); 404 Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0FeedbackScale, 0x00, 405 glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale]); 406 Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PostScale, 0x00, 407 glintReg->DacRegs[PM2VDACRDDClk0PostScale]); 408 Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03); 409} 410 411static void 412Permedia2vShowCursor(ScrnInfoPtr pScrn) 413{ 414 /* Enable cursor - X11 mode */ 415 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x11); 416} 417 418static void Permedia2vLoadCursorCallback(ScrnInfoPtr pScrn); 419 420static void 421Permedia2vHideCursor(ScrnInfoPtr pScrn) 422{ 423 GLINTPtr pGlint = GLINTPTR(pScrn); 424 425 /* Disable cursor - X11 mode */ 426 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x10); 427 428 /* 429 * For some reason, we need to clear the image as well as disable 430 * the cursor on PM2V, but not on PM3. The problem is noticeable 431 * only when running multi-head, as you can see the cursor get 432 * "left behind" on the screen it is leaving... 433 */ 434 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA2V) { 435 memset(pGlint->HardwareCursorPattern, 0, 1024); 436 pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback; 437 } 438} 439 440static void 441Permedia2vLoadCursorCallback( 442 ScrnInfoPtr pScrn 443) 444{ 445 GLINTPtr pGlint = GLINTPTR(pScrn); 446 int i; 447 448 for (i=0; i<1024; i++) 449 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPattern+i, 0x00, 450 pGlint->HardwareCursorPattern[i]); 451 452 pGlint->LoadCursorCallback = NULL; 453} 454 455static void 456Permedia2vLoadCursorImage( 457 ScrnInfoPtr pScrn, 458 unsigned char *src 459) 460{ 461 GLINTPtr pGlint = GLINTPTR(pScrn); 462 int i; 463 464 for (i=0; i<1024; i++) 465 pGlint->HardwareCursorPattern[i] = *(src++); 466 467 pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback; 468} 469 470static void 471Permedia2vSetCursorPosition( 472 ScrnInfoPtr pScrn, 473 int x, int y 474) 475{ 476 x += 64; 477 y += 64; 478 /* Output position - "only" 11 bits of location documented */ 479 480 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotX, 0x00, 0x3f); 481 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotY, 0x00, 0x3f); 482 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXLow, 0x00, x & 0xFF); 483 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXHigh, 0x00, (x>>8) & 0x0F); 484 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYLow, 0x00, y & 0xFF); 485 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYHigh, 0x00, (y>>8) & 0x0F); 486 Permedia2vOutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x00); 487} 488 489static void 490Permedia2vCursorColorCallback( 491 ScrnInfoPtr pScrn 492) 493{ 494 GLINTPtr pGlint = GLINTPTR(pScrn); 495 int fg = pGlint->FGCursor; 496 int bg = pGlint->BGCursor; 497 498 if ((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA3) || 499 ((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) && 500 (pGlint->MultiChip == PCI_CHIP_PERMEDIA3)) ) { 501 /* PM3 uses last 2 indexes into hardware cursor palette fg first...*/ 502 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+39, 0x00, (fg>>16)&0xff); 503 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+40, 0x00, (fg>>8)&0xff); 504 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+41, 0x00, fg & 0xff); 505 506 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+42, 0x00, (bg>>16)&0xff); 507 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+43, 0x00, (bg>>8)&0xff); 508 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+44, 0x00, bg & 0xff); 509 } else { 510 /* PM2v uses first 2 indexes into hardware cursor palette bg first...*/ 511 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+0, 0x00, (bg>>16)&0xff); 512 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+1, 0x00, (bg>>8)&0xff); 513 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+2, 0x00, bg & 0xff); 514 515 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+3, 0x00, (fg>>16)&0xff); 516 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+4, 0x00, (fg>>8)&0xff); 517 Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+5, 0x00, fg & 0xff); 518 } 519 pGlint->CursorColorCallback = NULL; 520} 521 522static void 523Permedia2vSetCursorColors( 524 ScrnInfoPtr pScrn, 525 int bg, int fg 526) 527{ 528 GLINTPtr pGlint = GLINTPTR(pScrn); 529 530 pGlint->FGCursor = fg; 531 pGlint->BGCursor = bg; 532 533 pGlint->CursorColorCallback = Permedia2vCursorColorCallback; 534} 535 536static Bool 537Permedia2vUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) 538{ 539 return TRUE; 540} 541 542Bool 543Permedia2vHWCursorInit(ScreenPtr pScreen) 544{ 545 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 546 GLINTPtr pGlint = GLINTPTR(pScrn); 547 xf86CursorInfoPtr infoPtr; 548 549 infoPtr = xf86CreateCursorInfoRec(); 550 if(!infoPtr) return FALSE; 551 552 pGlint->CursorInfoRec = infoPtr; 553 554 infoPtr->MaxWidth = 64; 555 infoPtr->MaxHeight = 64; 556 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 557#if X_BYTE_ORDER == X_BIG_ENDIAN 558 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 559#endif 560 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; 561 infoPtr->SetCursorColors = Permedia2vSetCursorColors; 562 infoPtr->SetCursorPosition = Permedia2vSetCursorPosition; 563 infoPtr->LoadCursorImage = Permedia2vLoadCursorImage; 564 infoPtr->HideCursor = Permedia2vHideCursor; 565 infoPtr->ShowCursor = Permedia2vShowCursor; 566 infoPtr->UseHWCursor = Permedia2vUseHWCursor; 567 568 return(xf86InitCursor(pScreen, infoPtr)); 569} 570