home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1993 by NeXT Computer, Inc as an unpublished work.
- * All rights reserved.
- *
- * S3ProgramDAC.m -- DAC support for the S3.
- *
- * History
- * Thu Sep 15 15:16:43 PDT 1994, James C. Lee
- * Added AT&T 20C505 DAC support
- * Author: Derek B Clegg 1 July 1993
- * Based on work by Joe Pasqua.
- */
- #import "S3.h"
-
- /* The `ProgramDAC' category of `S3'. */
-
- @implementation S3 (ProgramDAC)
-
- static inline void
- setCommandRegister0(unsigned char value)
- {
- rwrite(VGA_CRTC_INDEX, 0x55, 0x01);
- outb(RS_02, value);
- }
-
- static inline void
- setCommandRegister1(unsigned char value)
- {
- rwrite(VGA_CRTC_INDEX, 0x55, 0x02);
- outb(RS_00, value);
- }
-
- static inline void
- setCommandRegister2(unsigned char value)
- {
- rwrite(VGA_CRTC_INDEX, 0x55, 0x02);
- outb(RS_01, value);
- }
-
- static inline void
- setCommandRegister3(unsigned char value)
- {
- unsigned char commandRegister0, addressRegister;
-
- rwrite(VGA_CRTC_INDEX, 0x55, 0x01);
- commandRegister0 = inb(RS_02);
- outb(RS_02, 0x80 | commandRegister0);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- addressRegister = inb(RS_00);
- outb(RS_00, 0x01);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x02);
- outb(RS_02, value);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x01);
- outb(RS_02, commandRegister0);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- outb(RS_00, addressRegister);
- }
-
- // also check for AT&T 20C505 DAC; it's BT485 compatible
- static DACtype checkForBrooktreeDAC(void)
- {
- DACtype dac;
- unsigned char commandRegister0;
-
- S3_unlockRegisters();
-
- /* Save the value of command register 0. */
- rwrite(VGA_CRTC_INDEX, 0x55, 0x01);
- commandRegister0 = inb(RS_02);
-
- /* Write a zero to bit 7 of command register 0. */
- outb(RS_02, commandRegister0 & ~(1 << 7));
-
- /* Read the status register. */
- rwrite(VGA_CRTC_INDEX, 0x55, 0x02);
- switch (inb(RS_02) & 0xF0) {
- case 0x40:
- dac = Bt484;
- break;
- case 0x80:
- dac = Bt485;
- break;
- case 0x20:
- dac = Bt485A;
- break;
- case 0xd0:
- dac = ATT20C505;
- break;
- default:
- dac = UnknownDAC;
- break;
- }
-
- /* Restore the old value of command register 0. */
- setCommandRegister0(commandRegister0);
-
- /* Make sure that we are addressing RS(00xx). */
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
-
- S3_lockRegisters();
-
- return dac;
- }
-
- - determineDACType
- {
- dac = checkForBrooktreeDAC();
- if (dac == UnknownDAC) {
- /* Assume that it's an AT&T 20C491 or some other compatible DAC,
- * such as the Sierra SC15025. */
- dac = ATT20C491;
- }
- return self;
- }
-
- - (BOOL)hasTransferTable
- {
- switch (dac) {
- case ATT20C491:
- if ([self displayInfo]->bitsPerPixel == IO_8BitsPerPixel)
- return YES;
- else
- return NO;
- break;
- case Bt484:
- case Bt485:
- case Bt485A:
- case ATT20C505:
- return YES;
- break;
- default:
- return NO;
- break;
- }
- }
-
- - (BOOL)needsSoftwareGammaCorrection
- {
- switch (dac) {
- case ATT20C491:
- return YES;
- break;
- case Bt484:
- case Bt485:
- case Bt485A:
- case ATT20C505:
- return NO;
- break;
- default:
- return YES;
- break;
- }
- }
-
- /* Default gamma precompensation table for color displays.
- * Gamma 2.2 LUT for P22 phosphor displays (Hitachi, NEC, generic VGA) */
-
- static const unsigned char gamma16[] = {
- 0, 74, 102, 123, 140, 155, 168, 180,
- 192, 202, 212, 221, 230, 239, 247, 255
- };
-
- static const unsigned char gamma8[] = {
- 0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52,
- 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 74, 76,
- 78, 79, 81, 82, 84, 85, 87, 88, 90, 91, 93, 94,
- 95, 97, 98, 99, 100, 102, 103, 104, 105, 107, 108, 109,
- 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122,
- 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 141, 142, 143, 144, 145,
- 146, 147, 148, 148, 149, 150, 151, 152, 153, 153, 154, 155,
- 156, 157, 158, 158, 159, 160, 161, 162, 162, 163, 164, 165,
- 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174,
- 174, 175, 176, 177, 177, 178, 179, 179, 180, 181, 182, 182,
- 183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190,
- 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198,
- 199, 200, 200, 201, 201, 202, 203, 203, 204, 205, 205, 206,
- 206, 207, 208, 208, 209, 210, 210, 211, 211, 212, 213, 213,
- 214, 214, 215, 216, 216, 217, 217, 218, 218, 219, 220, 220,
- 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
- 228, 228, 229, 229, 230, 230, 231, 231, 232, 233, 233, 234,
- 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240,
- 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246,
- 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252,
- 253, 253, 254, 255,
- };
-
- static void
- SetGammaValue(unsigned int r, unsigned int g, unsigned int b, int level)
- {
- outb(RS_01, EV_SCALE_BRIGHTNESS(level, r));
- outb(RS_01, EV_SCALE_BRIGHTNESS(level, g));
- outb(RS_01, EV_SCALE_BRIGHTNESS(level, b));
- }
-
- - setGammaTable
- {
- unsigned int i, j, g;
- const IODisplayInfo *displayInfo;
-
- displayInfo = [self displayInfo];
-
- outb(RS_00, 0x00);
-
- switch (dac) {
- case Bt484:
- case Bt485:
- case Bt485A:
- case ATT20C505:
- if (redTransferTable != 0) {
- for (i = 0; i < transferTableCount; i++) {
- for (j = 0; j < 256/transferTableCount; j++) {
- SetGammaValue(redTransferTable[i], greenTransferTable[i],
- blueTransferTable[i], brightnessLevel);
- }
- }
- } else {
- switch (displayInfo->bitsPerPixel) {
- case IO_24BitsPerPixel:
- case IO_8BitsPerPixel:
- for (g = 0; g < 256; g++) {
- SetGammaValue(gamma8[g], gamma8[g], gamma8[g],
- brightnessLevel);
- }
- break;
-
- case IO_15BitsPerPixel:
- for (i = 0; i < 32; i++) {
- for (j = 0; j < 8; j++) {
- SetGammaValue(gamma16[i/2], gamma16[i/2], gamma16[i/2],
- brightnessLevel);
- }
- }
- break;
- default:
- break;
- }
- }
- break;
-
- case ATT20C491: /* ATT20C491 or other compatible DAC. */
- switch (displayInfo->bitsPerPixel) {
- const unsigned char *rTable, *gTable, *bTable;
- case IO_8BitsPerPixel:
-
- /* Write out the gamma-corrected grayscale palette. */
- if (redTransferTable != 0) {
- rTable = redTransferTable;
- gTable = greenTransferTable;
- bTable = blueTransferTable;
- } else {
- rTable = gTable = bTable = gamma8;
- }
- for (g = 0; g < 256; g++) {
- unsigned int r,gr,b;
- r = rTable[g] * 63 / 255;
- gr = gTable[g] * 63 / 255;
- b = bTable[g] * 63 / 255;
- SetGammaValue(r, gr, b, brightnessLevel);
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- return self;
- }
-
- - resetDAC
- {
- const IODisplayInfo *displayInfo;
-
- displayInfo = [self displayInfo];
-
- switch (dac) {
- case ATT20C491:
- inb(RS_03); /* Take DAC out of command mode. */
- inb(RS_02); /* Four reads to get DAC into command mode */
- inb(RS_02);
- inb(RS_02);
- inb(RS_02);
- outb(RS_02, 0x00); /* Get DAC into 8bpp mode. */
- inb(RS_03); /* Take DAC out of command mode. */
- rwrite(VGA_CRTC_INDEX, 0x45, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- break;
-
- case Bt484:
- case Bt485:
- case Bt485A:
- case ATT20C505:
- setCommandRegister0(0x00);
- setCommandRegister1(0x00);
- setCommandRegister2(0x00);
- if (dac == Bt485 || dac == Bt485A || dac == ATT20C505)
- setCommandRegister3(0x00);
- rwrite(VGA_CRTC_INDEX, 0x45, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- rrmw(VGA_CRTC_INDEX, 0x55, ~S3_DAC_R_SEL_MASK, 0x00);
- default:
- break;
- }
-
- /* Restore the PIXEL mask. */
- outb(RS_02, 0xFF);
-
- /* Set correct falling edge mode. */
- rrmw(VGA_CRTC_INDEX, S3_EXT_MODE, 0xFE, 0x00);
-
- return self;
- }
-
- - programDAC
- {
- const IODisplayInfo *displayInfo;
-
- displayInfo = [self displayInfo];
-
- switch (dac) {
- case ATT20C491:
- inb(RS_03); /* Take DAC out of command mode. */
- inb(RS_02); /* Four reads to get DAC into command mode */
- inb(RS_02);
- inb(RS_02);
- inb(RS_02);
-
- switch (displayInfo->bitsPerPixel) {
- case IO_8BitsPerPixel:
- outb(RS_02, 0x00); /* Get DAC into 8bpp mode. */
- break;
- case IO_15BitsPerPixel:
- outb(RS_02, 0xA0); /* Get DAC into 15bpp mode. */
- break;
- default:
- break;
- }
- inb(RS_03); /* Take DAC out of command mode. */
- rwrite(VGA_CRTC_INDEX, 0x45, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- break;
-
- case Bt484:
- case Bt485:
- case Bt485A:
- case ATT20C505:
- switch (displayInfo->bitsPerPixel) {
- case IO_8BitsPerPixel:
- if (displayInfo->width == 1280) {
- setCommandRegister0(0x02);
- setCommandRegister1(0x40);
- setCommandRegister2(0x30);
- if (dac == Bt485 || dac == Bt485A || dac == ATT20C505)
- setCommandRegister3(0x08);
- rwrite(VGA_CRTC_INDEX, 0x45, 0x20);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x28);
- } else {
- setCommandRegister0(0x02);
- setCommandRegister1(0x00);
- setCommandRegister2(0x00);
- if (dac == Bt485 || dac == Bt485A || dac == ATT20C505)
- setCommandRegister3(0x00);
- rwrite(VGA_CRTC_INDEX, 0x45, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x00);
- }
- break;
-
- case IO_15BitsPerPixel:
- setCommandRegister0(0x02);
- setCommandRegister1(0x20);
- setCommandRegister2(0x30);
- if (dac == Bt485 || dac == Bt485A || dac == ATT20C505)
- setCommandRegister3(0x00);
- if (displayInfo->width == 1280)
- rwrite(VGA_CRTC_INDEX, 0x53, 0x20);
- else
- rwrite(VGA_CRTC_INDEX, 0x53, 0x00);
- rwrite(VGA_CRTC_INDEX, 0x45, 0x20);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x28);
- break;
-
- case IO_24BitsPerPixel:
- setCommandRegister0(0x02);
- setCommandRegister1(0x00);
- setCommandRegister2(0x30);
- if (dac == Bt485 || dac == Bt485A || dac == ATT20C505)
- setCommandRegister3(0x08);
- rwrite(VGA_CRTC_INDEX, 0x45, 0x20);
- rwrite(VGA_CRTC_INDEX, 0x53, 0x20);
- rwrite(VGA_CRTC_INDEX, 0x55, 0x28);
- break;
-
- default:
- break;
- }
- rrmw(VGA_CRTC_INDEX, 0x55, ~S3_DAC_R_SEL_MASK, 0x00);
- break;
-
- default:
- break;
- }
-
- /* Restore the PIXEL mask. */
- outb(RS_02, 0xFF);
-
- /* Set correct falling edge mode. */
- rrmw(VGA_CRTC_INDEX, S3_EXT_MODE, 0xFE, 0x00);
-
- return self;
- }
- @end
-