|
|
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.