atidac.c revision 32b578d3
1/* 2 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 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 copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France 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 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE 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 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include <string.h> 28 29#include "ati.h" 30#include "atidac.h" 31#include "atimach64io.h" 32 33/* 34 * RAMDAC-related definitions. 35 */ 36const SymTabRec ATIDACDescriptors[] = 37{ /* Keep this table in ascending DACType order */ 38 {ATI_DAC_ATI68830, "ATI 68830 or similar"}, 39 {ATI_DAC_SC11483, "Sierra 11483 or similar"}, 40 {ATI_DAC_ATI68875, "ATI 68875 or similar"}, 41 {ATI_DAC_TVP3026_A, "TI ViewPoint3026 or similar"}, 42 {ATI_DAC_GENERIC, "Brooktree 476 or similar"}, 43 {ATI_DAC_BT481, "Brooktree 481 or similar"}, 44 {ATI_DAC_ATT20C491, "AT&T 20C491 or similar"}, 45 {ATI_DAC_SC15026, "Sierra 15026 or similar"}, 46 {ATI_DAC_MU9C1880, "Music 9C1880 or similar"}, 47 {ATI_DAC_IMSG174, "Inmos G174 or similar"}, 48 {ATI_DAC_ATI68860_B, "ATI 68860 (Revision B) or similar"}, 49 {ATI_DAC_ATI68860_C, "ATI 68860 (Revision C) or similar"}, 50 {ATI_DAC_TVP3026_B, "TI ViewPoint3026 or similar"}, 51 {ATI_DAC_STG1700, "SGS-Thompson 1700 or similar"}, 52 {ATI_DAC_ATT20C498, "AT&T 20C498 or similar"}, 53 {ATI_DAC_STG1702, "SGS-Thompson 1702 or similar"}, 54 {ATI_DAC_SC15021, "Sierra 15021 or similar"}, 55 {ATI_DAC_ATT21C498, "AT&T 21C498 or similar"}, 56 {ATI_DAC_STG1703, "SGS-Thompson 1703 or similar"}, 57 {ATI_DAC_CH8398, "Chrontel 8398 or similar"}, 58 {ATI_DAC_ATT20C408, "AT&T 20C408 or similar"}, 59 {ATI_DAC_INTERNAL, "Internal"}, 60 {ATI_DAC_IBMRGB514, "IBM RGB 514 or similar"}, 61 {ATI_DAC_UNKNOWN, "Unknown"} /* Must be last */ 62}; 63 64#ifndef AVOID_CPIO 65 66/* 67 * ATISetDACIOPorts -- 68 * 69 * This function sets up DAC access I/O port numbers. 70 */ 71void 72ATISetDACIOPorts 73( 74 ATIPtr pATI, 75 ATICRTCType crtc 76) 77{ 78 switch (crtc) 79 { 80 case ATI_CRTC_VGA: 81 pATI->CPIO_DAC_DATA = VGA_DAC_DATA; 82 pATI->CPIO_DAC_MASK = VGA_DAC_MASK; 83 pATI->CPIO_DAC_READ = VGA_DAC_READ; 84 pATI->CPIO_DAC_WRITE = VGA_DAC_WRITE; 85 pATI->CPIO_DAC_WAIT = GENS1(pATI->CPIO_VGABase); 86 break; 87 88 case ATI_CRTC_8514: 89 pATI->CPIO_DAC_DATA = IBM_DAC_DATA; 90 pATI->CPIO_DAC_MASK = IBM_DAC_MASK; 91 pATI->CPIO_DAC_READ = IBM_DAC_READ; 92 pATI->CPIO_DAC_WRITE = IBM_DAC_WRITE; 93 pATI->CPIO_DAC_WAIT = pATI->CPIO_DAC_MASK; 94 break; 95 96 case ATI_CRTC_MACH64: 97 pATI->CPIO_DAC_DATA = ATIIOPort(DAC_REGS) + 1; 98 pATI->CPIO_DAC_MASK = ATIIOPort(DAC_REGS) + 2; 99 pATI->CPIO_DAC_READ = ATIIOPort(DAC_REGS) + 3; 100 pATI->CPIO_DAC_WRITE = ATIIOPort(DAC_REGS) + 0; 101 pATI->CPIO_DAC_WAIT = pATI->CPIOBase; 102 break; 103 104 default: 105 break; 106 } 107} 108 109#endif /* AVOID_CPIO */ 110 111/* 112 * ATIGetDACCmdReg -- 113 * 114 * Setup to access a RAMDAC's command register. 115 */ 116CARD8 117ATIGetDACCmdReg 118( 119 ATIPtr pATI 120) 121{ 122 123#ifdef AVOID_CPIO 124 125 (void)in8(M64_DAC_WRITE); /* Reset to PEL mode */ 126 (void)in8(M64_DAC_MASK); 127 (void)in8(M64_DAC_MASK); 128 (void)in8(M64_DAC_MASK); 129 return in8(M64_DAC_MASK); 130 131#else /* AVOID_CPIO */ 132 133 (void)inb(pATI->CPIO_DAC_WRITE); /* Reset to PEL mode */ 134 (void)inb(pATI->CPIO_DAC_MASK); 135 (void)inb(pATI->CPIO_DAC_MASK); 136 (void)inb(pATI->CPIO_DAC_MASK); 137 return inb(pATI->CPIO_DAC_MASK); 138 139#endif /* AVOID_CPIO */ 140 141} 142 143/* 144 * ATIDACPreInit -- 145 * 146 * This function initialises the fields in an ATIHWRec that relate to DACs. 147 */ 148void 149ATIDACPreInit 150( 151 ScrnInfoPtr pScreenInfo, 152 ATIPtr pATI, 153 ATIHWPtr pATIHW 154) 155{ 156 int Index, Index2; 157 CARD8 maxColour = (1 << pATI->rgbBits) - 1; 158 159 pATIHW->dac_read = pATIHW->dac_write = 0x00U; 160 pATIHW->dac_mask = 0xFFU; 161 162 /* 163 * Set colour lookup table. The first entry has already been zeroed out. 164 */ 165 if (pATI->depth > 8) 166 for (Index = 1; Index < (NumberOf(pATIHW->lut) / 3); Index++) 167 { 168 Index2 = Index * 3; 169 pATIHW->lut[Index2 + 0] = 170 pATIHW->lut[Index2 + 1] = 171 pATIHW->lut[Index2 + 2] = Index; 172 } 173 else 174 { 175 /* 176 * Initialise hardware colour map so that use of uninitialised 177 * software colour map entries can easily be seen. For 256-colour 178 * modes, this doesn't remain effective for very long... 179 */ 180 pATIHW->lut[3] = pATIHW->lut[4] = pATIHW->lut[5] = 0xFFU; 181 for (Index = 2; Index < (NumberOf(pATIHW->lut) / 3); Index++) 182 { 183 Index2 = Index * 3; 184 pATIHW->lut[Index2 + 0] = maxColour; 185 pATIHW->lut[Index2 + 1] = 0x00U; 186 pATIHW->lut[Index2 + 2] = maxColour; 187 } 188 } 189} 190 191/* 192 * ATIDACSave -- 193 * 194 * This function is called to save the current RAMDAC state into an ATIHWRec 195 * structure occurrence. 196 */ 197void 198ATIDACSave 199( 200 ATIPtr pATI, 201 ATIHWPtr pATIHW 202) 203{ 204 int Index; 205 206#ifdef AVOID_CPIO 207 208 pATIHW->dac_read = in8(M64_DAC_READ); 209 DACDelay; 210 pATIHW->dac_write = in8(M64_DAC_WRITE); 211 DACDelay; 212 pATIHW->dac_mask = in8(M64_DAC_MASK); 213 DACDelay; 214 215 /* Save DAC's colour lookup table */ 216 out8(M64_DAC_MASK, 0xFFU); 217 DACDelay; 218 out8(M64_DAC_READ, 0x00U); 219 DACDelay; 220 for (Index = 0; Index < NumberOf(pATIHW->lut); Index++) 221 { 222 pATIHW->lut[Index] = in8(M64_DAC_DATA); 223 DACDelay; 224 } 225 226 out8(M64_DAC_MASK, pATIHW->dac_mask); 227 DACDelay; 228 out8(M64_DAC_READ, pATIHW->dac_read); 229 DACDelay; 230 231#else /* AVOID_CPIO */ 232 233 ATISetDACIOPorts(pATI, pATIHW->crtc); 234 235 pATIHW->dac_read = inb(pATI->CPIO_DAC_READ); 236 DACDelay; 237 pATIHW->dac_write = inb(pATI->CPIO_DAC_WRITE); 238 DACDelay; 239 pATIHW->dac_mask = inb(pATI->CPIO_DAC_MASK); 240 DACDelay; 241 242 /* Save DAC's colour lookup table */ 243 outb(pATI->CPIO_DAC_MASK, 0xFFU); 244 DACDelay; 245 outb(pATI->CPIO_DAC_READ, 0x00U); 246 DACDelay; 247 for (Index = 0; Index < NumberOf(pATIHW->lut); Index++) 248 { 249 pATIHW->lut[Index] = inb(pATI->CPIO_DAC_DATA); 250 DACDelay; 251 } 252 253 outb(pATI->CPIO_DAC_MASK, pATIHW->dac_mask); 254 DACDelay; 255 outb(pATI->CPIO_DAC_READ, pATIHW->dac_read); 256 DACDelay; 257 258#endif /* AVOID_CPIO */ 259 260} 261 262/* 263 * ATIDACSet -- 264 * 265 * This function loads RAMDAC data from an ATIHWRec structure occurrence. 266 */ 267void 268ATIDACSet 269( 270 ATIPtr pATI, 271 ATIHWPtr pATIHW 272) 273{ 274 int Index; 275 276#ifdef AVOID_CPIO 277 278 /* Load DAC's colour lookup table */ 279 out8(M64_DAC_MASK, 0xFFU); 280 DACDelay; 281 out8(M64_DAC_WRITE, 0x00U); 282 DACDelay; 283 for (Index = 0; Index < NumberOf(pATIHW->lut); Index++) 284 { 285 out8(M64_DAC_DATA, pATIHW->lut[Index]); 286 DACDelay; 287 } 288 289 out8(M64_DAC_MASK, pATIHW->dac_mask); 290 DACDelay; 291 out8(M64_DAC_READ, pATIHW->dac_read); 292 DACDelay; 293 out8(M64_DAC_WRITE, pATIHW->dac_write); 294 DACDelay; 295 296#else /* AVOID_CPIO */ 297 298 ATISetDACIOPorts(pATI, pATIHW->crtc); 299 300 /* Load DAC's colour lookup table */ 301 outb(pATI->CPIO_DAC_MASK, 0xFFU); 302 DACDelay; 303 outb(pATI->CPIO_DAC_WRITE, 0x00U); 304 DACDelay; 305 for (Index = 0; Index < NumberOf(pATIHW->lut); Index++) 306 { 307 outb(pATI->CPIO_DAC_DATA, pATIHW->lut[Index]); 308 DACDelay; 309 } 310 311 outb(pATI->CPIO_DAC_MASK, pATIHW->dac_mask); 312 DACDelay; 313 outb(pATI->CPIO_DAC_READ, pATIHW->dac_read); 314 DACDelay; 315 outb(pATI->CPIO_DAC_WRITE, pATIHW->dac_write); 316 DACDelay; 317 318#endif /* AVOID_CPIO */ 319 320} 321 322/* 323 * ATISetLUTEntry -- 324 * 325 * This function is called to set one of a DAC's LUT entries. 326 */ 327static void 328ATISetLUTEntry 329( 330 ATIPtr pATI, 331 int Index, 332 CARD8 *LUTEntry 333) 334{ 335#ifdef AVOID_CPIO 336 337 out8(M64_DAC_WRITE, Index); 338 DACDelay; 339 out8(M64_DAC_DATA, LUTEntry[0]); 340 DACDelay; 341 out8(M64_DAC_DATA, LUTEntry[1]); 342 DACDelay; 343 out8(M64_DAC_DATA, LUTEntry[2]); 344 DACDelay; 345 346#else /* AVOID_CPIO */ 347 348 outb(pATI->CPIO_DAC_WRITE, Index); 349 DACDelay; 350 outb(pATI->CPIO_DAC_DATA, LUTEntry[0]); 351 DACDelay; 352 outb(pATI->CPIO_DAC_DATA, LUTEntry[1]); 353 DACDelay; 354 outb(pATI->CPIO_DAC_DATA, LUTEntry[2]); 355 DACDelay; 356 357#endif /* AVOID_CPIO */ 358} 359 360/* 361 * ATILoadPalette -- 362 * 363 * This function updates the RAMDAC's LUT and the in-memory copy of it in 364 * NewHW. 365 */ 366void 367ATILoadPalette 368( 369 ScrnInfoPtr pScreenInfo, 370 int nColours, 371 int *Indices, 372 LOCO *Colours, 373 VisualPtr pVisual 374) 375{ 376 ATIPtr pATI = ATIPTR(pScreenInfo); 377 CARD8 *LUTEntry; 378 int i, j, Index; 379 380 if (((pVisual->class | DynamicClass) == DirectColor) && 381 ((1 << pVisual->nplanes) > (SizeOf(pATI->NewHW.lut) / 3))) 382 { 383 int reds = pVisual->redMask >> pVisual->offsetRed; 384 int greens = pVisual->greenMask >> pVisual->offsetGreen; 385 int blues = pVisual->blueMask >> pVisual->offsetBlue; 386 387 int redShift = 8 - pATI->weight.red; 388 int greenShift = 8 - pATI->weight.green; 389 int blueShift = 8 - pATI->weight.blue; 390 391 int redMult = 3 << redShift; 392 int greenMult = 3 << greenShift; 393 int blueMult = 3 << blueShift; 394 395 int minShift; 396 397 CARD8 fChanged[SizeOf(pATI->NewHW.lut) / 3]; 398 399 (void)memset(fChanged, 0, SizeOf(fChanged)); 400 401 minShift = redShift; 402 if (minShift > greenShift) 403 minShift = greenShift; 404 if (minShift > blueShift) 405 minShift = blueShift; 406 407 for (i = 0; i < nColours; i++) 408 { 409 if((Index = Indices[i]) < 0) 410 continue; 411 412 if (Index <= reds) 413 { 414 j = Index * redMult; 415 pATI->NewHW.lut[j + 0] = Colours[Index].red; 416 fChanged[j / 3] = TRUE; 417 } 418 if (Index <= greens) 419 { 420 j = Index * greenMult; 421 pATI->NewHW.lut[j + 1] = Colours[Index].green; 422 fChanged[j / 3] = TRUE; 423 } 424 if (Index <= blues) 425 { 426 j = Index * blueMult; 427 pATI->NewHW.lut[j + 2] = Colours[Index].blue; 428 fChanged[j / 3] = TRUE; 429 } 430 } 431 432 if (pScreenInfo->vtSema || pATI->currentMode) 433 { 434 /* Rewrite LUT entries that could have been changed */ 435 i = 1 << minShift; 436 LUTEntry = pATI->NewHW.lut; 437 438 for (Index = 0; 439 Index < (SizeOf(pATI->NewHW.lut) / 3); 440 Index += i, LUTEntry += i * 3) 441 if (fChanged[Index]) 442 ATISetLUTEntry(pATI, Index, LUTEntry); 443 } 444 } 445 else 446 { 447 for (i = 0; i < nColours; i++) 448 { 449 Index = Indices[i]; 450 if ((Index < 0) || (Index >= (SizeOf(pATI->NewHW.lut) / 3))) 451 continue; 452 453 LUTEntry = &pATI->NewHW.lut[Index * 3]; 454 LUTEntry[0] = Colours[Index].red; 455 LUTEntry[1] = Colours[Index].green; 456 LUTEntry[2] = Colours[Index].blue; 457 458 if (pScreenInfo->vtSema || pATI->currentMode) 459 ATISetLUTEntry(pATI, Index, LUTEntry); 460 } 461 } 462} 463