home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Examples / DriverKit / S3 / S3_reloc.tproj / S3ProgramDAC.m < prev    next >
Encoding:
Text File  |  1994-09-26  |  10.0 KB  |  418 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.  * 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
  418.