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