home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Examples / DriverKit / S3 / S3_reloc.tproj / S3ProgramDAC.m < prev    next >
Encoding:
Text File  |  1993-08-13  |  9.3 KB  |  388 lines

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