|
|
1.1 ! root 1: /* Copyright (c) 1993 by NeXT Computer, Inc as an unpublished work. ! 2: * All rights reserved. ! 3: * ! 4: * S3ProgramDAC.m -- DAC support for the S3. ! 5: * ! 6: * History ! 7: * Thu Sep 15 15:16:43 PDT 1994, James C. Lee ! 8: * Added AT&T 20C505 DAC support ! 9: * Author: Derek B Clegg 1 July 1993 ! 10: * Based on work by Joe Pasqua. ! 11: */ ! 12: #import "S3.h" ! 13: ! 14: /* The `ProgramDAC' category of `S3'. */ ! 15: ! 16: @implementation S3 (ProgramDAC) ! 17: ! 18: static inline void ! 19: setCommandRegister0(unsigned char value) ! 20: { ! 21: rwrite(VGA_CRTC_INDEX, 0x55, 0x01); ! 22: outb(RS_02, value); ! 23: } ! 24: ! 25: static inline void ! 26: setCommandRegister1(unsigned char value) ! 27: { ! 28: rwrite(VGA_CRTC_INDEX, 0x55, 0x02); ! 29: outb(RS_00, value); ! 30: } ! 31: ! 32: static inline void ! 33: setCommandRegister2(unsigned char value) ! 34: { ! 35: rwrite(VGA_CRTC_INDEX, 0x55, 0x02); ! 36: outb(RS_01, value); ! 37: } ! 38: ! 39: static inline void ! 40: setCommandRegister3(unsigned char value) ! 41: { ! 42: unsigned char commandRegister0, addressRegister; ! 43: ! 44: rwrite(VGA_CRTC_INDEX, 0x55, 0x01); ! 45: commandRegister0 = inb(RS_02); ! 46: outb(RS_02, 0x80 | commandRegister0); ! 47: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 48: addressRegister = inb(RS_00); ! 49: outb(RS_00, 0x01); ! 50: rwrite(VGA_CRTC_INDEX, 0x55, 0x02); ! 51: outb(RS_02, value); ! 52: rwrite(VGA_CRTC_INDEX, 0x55, 0x01); ! 53: outb(RS_02, commandRegister0); ! 54: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 55: outb(RS_00, addressRegister); ! 56: } ! 57: ! 58: // also check for AT&T 20C505 DAC; it's BT485 compatible ! 59: static DACtype checkForBrooktreeDAC(void) ! 60: { ! 61: DACtype dac; ! 62: unsigned char commandRegister0; ! 63: ! 64: S3_unlockRegisters(); ! 65: ! 66: /* Save the value of command register 0. */ ! 67: rwrite(VGA_CRTC_INDEX, 0x55, 0x01); ! 68: commandRegister0 = inb(RS_02); ! 69: ! 70: /* Write a zero to bit 7 of command register 0. */ ! 71: outb(RS_02, commandRegister0 & ~(1 << 7)); ! 72: ! 73: /* Read the status register. */ ! 74: rwrite(VGA_CRTC_INDEX, 0x55, 0x02); ! 75: switch (inb(RS_02) & 0xF0) { ! 76: case 0x40: ! 77: dac = Bt484; ! 78: break; ! 79: case 0x80: ! 80: dac = Bt485; ! 81: break; ! 82: case 0x20: ! 83: dac = Bt485A; ! 84: break; ! 85: case 0xd0: ! 86: dac = ATT20C505; ! 87: break; ! 88: default: ! 89: dac = UnknownDAC; ! 90: break; ! 91: } ! 92: ! 93: /* Restore the old value of command register 0. */ ! 94: setCommandRegister0(commandRegister0); ! 95: ! 96: /* Make sure that we are addressing RS(00xx). */ ! 97: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 98: ! 99: S3_lockRegisters(); ! 100: ! 101: return dac; ! 102: } ! 103: ! 104: - determineDACType ! 105: { ! 106: dac = checkForBrooktreeDAC(); ! 107: if (dac == UnknownDAC) { ! 108: /* Assume that it's an AT&T 20C491 or some other compatible DAC, ! 109: * such as the Sierra SC15025. */ ! 110: dac = ATT20C491; ! 111: } ! 112: return self; ! 113: } ! 114: ! 115: - (BOOL)hasTransferTable ! 116: { ! 117: switch (dac) { ! 118: case ATT20C491: ! 119: if ([self displayInfo]->bitsPerPixel == IO_8BitsPerPixel) ! 120: return YES; ! 121: else ! 122: return NO; ! 123: break; ! 124: case Bt484: ! 125: case Bt485: ! 126: case Bt485A: ! 127: case ATT20C505: ! 128: return YES; ! 129: break; ! 130: default: ! 131: return NO; ! 132: break; ! 133: } ! 134: } ! 135: ! 136: - (BOOL)needsSoftwareGammaCorrection ! 137: { ! 138: switch (dac) { ! 139: case ATT20C491: ! 140: return YES; ! 141: break; ! 142: case Bt484: ! 143: case Bt485: ! 144: case Bt485A: ! 145: case ATT20C505: ! 146: return NO; ! 147: break; ! 148: default: ! 149: return YES; ! 150: break; ! 151: } ! 152: } ! 153: ! 154: /* Default gamma precompensation table for color displays. ! 155: * Gamma 2.2 LUT for P22 phosphor displays (Hitachi, NEC, generic VGA) */ ! 156: ! 157: static const unsigned char gamma16[] = { ! 158: 0, 74, 102, 123, 140, 155, 168, 180, ! 159: 192, 202, 212, 221, 230, 239, 247, 255 ! 160: }; ! 161: ! 162: static const unsigned char gamma8[] = { ! 163: 0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, ! 164: 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 74, 76, ! 165: 78, 79, 81, 82, 84, 85, 87, 88, 90, 91, 93, 94, ! 166: 95, 97, 98, 99, 100, 102, 103, 104, 105, 107, 108, 109, ! 167: 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122, ! 168: 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, ! 169: 135, 136, 137, 138, 139, 140, 141, 141, 142, 143, 144, 145, ! 170: 146, 147, 148, 148, 149, 150, 151, 152, 153, 153, 154, 155, ! 171: 156, 157, 158, 158, 159, 160, 161, 162, 162, 163, 164, 165, ! 172: 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, ! 173: 174, 175, 176, 177, 177, 178, 179, 179, 180, 181, 182, 182, ! 174: 183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, ! 175: 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, ! 176: 199, 200, 200, 201, 201, 202, 203, 203, 204, 205, 205, 206, ! 177: 206, 207, 208, 208, 209, 210, 210, 211, 211, 212, 213, 213, ! 178: 214, 214, 215, 216, 216, 217, 217, 218, 218, 219, 220, 220, ! 179: 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, ! 180: 228, 228, 229, 229, 230, 230, 231, 231, 232, 233, 233, 234, ! 181: 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, ! 182: 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, ! 183: 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, ! 184: 253, 253, 254, 255, ! 185: }; ! 186: ! 187: static void ! 188: SetGammaValue(unsigned int r, unsigned int g, unsigned int b, int level) ! 189: { ! 190: outb(RS_01, EV_SCALE_BRIGHTNESS(level, r)); ! 191: outb(RS_01, EV_SCALE_BRIGHTNESS(level, g)); ! 192: outb(RS_01, EV_SCALE_BRIGHTNESS(level, b)); ! 193: } ! 194: ! 195: - setGammaTable ! 196: { ! 197: unsigned int i, j, g; ! 198: const IODisplayInfo *displayInfo; ! 199: ! 200: displayInfo = [self displayInfo]; ! 201: ! 202: outb(RS_00, 0x00); ! 203: ! 204: switch (dac) { ! 205: case Bt484: ! 206: case Bt485: ! 207: case Bt485A: ! 208: case ATT20C505: ! 209: if (redTransferTable != 0) { ! 210: for (i = 0; i < transferTableCount; i++) { ! 211: for (j = 0; j < 256/transferTableCount; j++) { ! 212: SetGammaValue(redTransferTable[i], greenTransferTable[i], ! 213: blueTransferTable[i], brightnessLevel); ! 214: } ! 215: } ! 216: } else { ! 217: switch (displayInfo->bitsPerPixel) { ! 218: case IO_24BitsPerPixel: ! 219: case IO_8BitsPerPixel: ! 220: for (g = 0; g < 256; g++) { ! 221: SetGammaValue(gamma8[g], gamma8[g], gamma8[g], ! 222: brightnessLevel); ! 223: } ! 224: break; ! 225: ! 226: case IO_15BitsPerPixel: ! 227: for (i = 0; i < 32; i++) { ! 228: for (j = 0; j < 8; j++) { ! 229: SetGammaValue(gamma16[i/2], gamma16[i/2], gamma16[i/2], ! 230: brightnessLevel); ! 231: } ! 232: } ! 233: break; ! 234: default: ! 235: break; ! 236: } ! 237: } ! 238: break; ! 239: ! 240: case ATT20C491: /* ATT20C491 or other compatible DAC. */ ! 241: switch (displayInfo->bitsPerPixel) { ! 242: const unsigned char *rTable, *gTable, *bTable; ! 243: case IO_8BitsPerPixel: ! 244: ! 245: /* Write out the gamma-corrected grayscale palette. */ ! 246: if (redTransferTable != 0) { ! 247: rTable = redTransferTable; ! 248: gTable = greenTransferTable; ! 249: bTable = blueTransferTable; ! 250: } else { ! 251: rTable = gTable = bTable = gamma8; ! 252: } ! 253: for (g = 0; g < 256; g++) { ! 254: unsigned int r,gr,b; ! 255: r = rTable[g] * 63 / 255; ! 256: gr = gTable[g] * 63 / 255; ! 257: b = bTable[g] * 63 / 255; ! 258: SetGammaValue(r, gr, b, brightnessLevel); ! 259: } ! 260: break; ! 261: default: ! 262: break; ! 263: } ! 264: break; ! 265: default: ! 266: break; ! 267: } ! 268: return self; ! 269: } ! 270: ! 271: - resetDAC ! 272: { ! 273: const IODisplayInfo *displayInfo; ! 274: ! 275: displayInfo = [self displayInfo]; ! 276: ! 277: switch (dac) { ! 278: case ATT20C491: ! 279: inb(RS_03); /* Take DAC out of command mode. */ ! 280: inb(RS_02); /* Four reads to get DAC into command mode */ ! 281: inb(RS_02); ! 282: inb(RS_02); ! 283: inb(RS_02); ! 284: outb(RS_02, 0x00); /* Get DAC into 8bpp mode. */ ! 285: inb(RS_03); /* Take DAC out of command mode. */ ! 286: rwrite(VGA_CRTC_INDEX, 0x45, 0x00); ! 287: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 288: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 289: break; ! 290: ! 291: case Bt484: ! 292: case Bt485: ! 293: case Bt485A: ! 294: case ATT20C505: ! 295: setCommandRegister0(0x00); ! 296: setCommandRegister1(0x00); ! 297: setCommandRegister2(0x00); ! 298: if (dac == Bt485 || dac == Bt485A || dac == ATT20C505) ! 299: setCommandRegister3(0x00); ! 300: rwrite(VGA_CRTC_INDEX, 0x45, 0x00); ! 301: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 302: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 303: rrmw(VGA_CRTC_INDEX, 0x55, ~S3_DAC_R_SEL_MASK, 0x00); ! 304: default: ! 305: break; ! 306: } ! 307: ! 308: /* Restore the PIXEL mask. */ ! 309: outb(RS_02, 0xFF); ! 310: ! 311: /* Set correct falling edge mode. */ ! 312: rrmw(VGA_CRTC_INDEX, S3_EXT_MODE, 0xFE, 0x00); ! 313: ! 314: return self; ! 315: } ! 316: ! 317: - programDAC ! 318: { ! 319: const IODisplayInfo *displayInfo; ! 320: ! 321: displayInfo = [self displayInfo]; ! 322: ! 323: switch (dac) { ! 324: case ATT20C491: ! 325: inb(RS_03); /* Take DAC out of command mode. */ ! 326: inb(RS_02); /* Four reads to get DAC into command mode */ ! 327: inb(RS_02); ! 328: inb(RS_02); ! 329: inb(RS_02); ! 330: ! 331: switch (displayInfo->bitsPerPixel) { ! 332: case IO_8BitsPerPixel: ! 333: outb(RS_02, 0x00); /* Get DAC into 8bpp mode. */ ! 334: break; ! 335: case IO_15BitsPerPixel: ! 336: outb(RS_02, 0xA0); /* Get DAC into 15bpp mode. */ ! 337: break; ! 338: default: ! 339: break; ! 340: } ! 341: inb(RS_03); /* Take DAC out of command mode. */ ! 342: rwrite(VGA_CRTC_INDEX, 0x45, 0x00); ! 343: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 344: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 345: break; ! 346: ! 347: case Bt484: ! 348: case Bt485: ! 349: case Bt485A: ! 350: case ATT20C505: ! 351: switch (displayInfo->bitsPerPixel) { ! 352: case IO_8BitsPerPixel: ! 353: if (displayInfo->width == 1280) { ! 354: setCommandRegister0(0x02); ! 355: setCommandRegister1(0x40); ! 356: setCommandRegister2(0x30); ! 357: if (dac == Bt485 || dac == Bt485A || dac == ATT20C505) ! 358: setCommandRegister3(0x08); ! 359: rwrite(VGA_CRTC_INDEX, 0x45, 0x20); ! 360: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 361: rwrite(VGA_CRTC_INDEX, 0x55, 0x28); ! 362: } else { ! 363: setCommandRegister0(0x02); ! 364: setCommandRegister1(0x00); ! 365: setCommandRegister2(0x00); ! 366: if (dac == Bt485 || dac == Bt485A || dac == ATT20C505) ! 367: setCommandRegister3(0x00); ! 368: rwrite(VGA_CRTC_INDEX, 0x45, 0x00); ! 369: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 370: rwrite(VGA_CRTC_INDEX, 0x55, 0x00); ! 371: } ! 372: break; ! 373: ! 374: case IO_15BitsPerPixel: ! 375: setCommandRegister0(0x02); ! 376: setCommandRegister1(0x20); ! 377: setCommandRegister2(0x30); ! 378: if (dac == Bt485 || dac == Bt485A || dac == ATT20C505) ! 379: setCommandRegister3(0x00); ! 380: if (displayInfo->width == 1280) ! 381: rwrite(VGA_CRTC_INDEX, 0x53, 0x20); ! 382: else ! 383: rwrite(VGA_CRTC_INDEX, 0x53, 0x00); ! 384: rwrite(VGA_CRTC_INDEX, 0x45, 0x20); ! 385: rwrite(VGA_CRTC_INDEX, 0x55, 0x28); ! 386: break; ! 387: ! 388: case IO_24BitsPerPixel: ! 389: setCommandRegister0(0x02); ! 390: setCommandRegister1(0x00); ! 391: setCommandRegister2(0x30); ! 392: if (dac == Bt485 || dac == Bt485A || dac == ATT20C505) ! 393: setCommandRegister3(0x08); ! 394: rwrite(VGA_CRTC_INDEX, 0x45, 0x20); ! 395: rwrite(VGA_CRTC_INDEX, 0x53, 0x20); ! 396: rwrite(VGA_CRTC_INDEX, 0x55, 0x28); ! 397: break; ! 398: ! 399: default: ! 400: break; ! 401: } ! 402: rrmw(VGA_CRTC_INDEX, 0x55, ~S3_DAC_R_SEL_MASK, 0x00); ! 403: break; ! 404: ! 405: default: ! 406: break; ! 407: } ! 408: ! 409: /* Restore the PIXEL mask. */ ! 410: outb(RS_02, 0xFF); ! 411: ! 412: /* Set correct falling edge mode. */ ! 413: rrmw(VGA_CRTC_INDEX, S3_EXT_MODE, 0xFE, 0x00); ! 414: ! 415: return self; ! 416: } ! 417: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.