home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / timing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-21  |  9.6 KB  |  272 lines

  1.  
  2. /* 
  3.  * Generic mode timing module.
  4.  */
  5.  
  6. #include "timing.h"    /* Types. */
  7.  
  8. #include "libvga.h"    /* for __svgalib_infotable (remove me) */
  9. #include "driver.h"    /* for __svgalib_monitortype (remove me) */
  10.  
  11. /* Standard mode timings. */
  12.  
  13. MonitorModeTiming standard_timings[] = {
  14. /* 320x200 @ 70 Hz, 31.5 kHz hsync */
  15. { 12588, 320, 336, 384, 400, 400, 409, 411, 450, DOUBLESCAN },
  16. /* 320x240 @ 60 Hz, 31.5 kHz hsync */
  17. { 12588, 320, 336, 384, 400, 480, 491, 493, 525, DOUBLESCAN },
  18. /* 320x240 @ 72 Hz, 36.5 kHz hsync */
  19. { 15750, 320, 336, 384, 400, 480, 488, 491, 521, DOUBLESCAN },
  20. /* 640x400 at 70 Hz, 31.5 kHz hsync */
  21. { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0 },
  22. /* 640x480 at 60 Hz, 31.5 kHz hsync */
  23. { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0 },
  24. /* 640x480 at 72 Hz, 36.5 kHz hsync */
  25. { 31500, 640, 680, 720, 864, 480, 488, 491, 521, 0 },
  26. /* 800x600 at 56 Hz, 35.15 kHz hsync */
  27. { 36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0 },
  28. /* 800x600 at 60 Hz, 37.8 kHz hsync */
  29. { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, PHSYNC | PVSYNC },
  30. /* 1024x768 at 87 Hz interlaced, 35.5 kHz hsync */
  31. { 44900, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED },
  32. /* 800x600 at 72 Hz, 48.0 kHz hsync */
  33. { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, PHSYNC | PVSYNC },
  34. /* 1024x768 at 60 Hz, 48.4 kHz hsync */
  35. { 65000, 1024, 1032, 1176, 1344, 768, 771, 777, 806, NHSYNC | NVSYNC },
  36. /* 1024x768 at 70 Hz, 56.6 kHz hsync */
  37. { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, NHSYNC | NVSYNC },
  38. /* 1280x1024 at 87 Hz interlaced, 51 kHz hsync */
  39. { 80000, 1280, 1296, 1512, 1568, 1024, 1025, 1037, 1165, INTERLACED },
  40. /* 1024x768 at 76 Hz, 62.5 kHz hsync */
  41. { 85000, 1024, 1032, 1152, 1360, 768, 784, 787, 823, 0 },
  42. /* 1280x1024 at 60 Hz, ? kHz hsync */
  43. { 110000, 1280, 1328, 1512, 1712, 1024, 1025, 1028, 1054, 0 },
  44. /* 1280x1024 at 70 Hz, ? kHz hsync */
  45. { 135000, 1280, 1312, 1456, 1712, 1024, 1027, 1030, 1064, 0 }
  46. };
  47.  
  48. #define NUMBER_OF_STANDARD_MODES \
  49.     (sizeof(standard_timings) / sizeof(standard_timings[0]))
  50.  
  51. /*
  52.  * Monitor spec checking is done with a fixed table, rather than
  53.  * calculations. The monitor types are defined in terms of the supported
  54.  * mode timings.
  55.  *
  56.  * This should be extended into a configuration file with mode timings,
  57.  * which are checked against monitor specs with calculations.
  58.  */
  59.  
  60. #define TIMING_WITHIN_MONITOR_SPEC(i) \
  61.     (timing_within_monitor_spec[__svgalib_monitortype] & (1 << i))
  62.  
  63. unsigned short timing_within_monitor_spec[7] = {
  64. /* type 0, 31.5 kHz */
  65.     0x07 +            /* doublescan modes */
  66.     0x08 + 0x10,        /* 640x400 and 640x480 at 60 Hz */
  67. /* type 1, 35.2 kHz */
  68.     0x1F + 0x40,        /* adds 800x600 @ 56 Hz */
  69. /* type 2, 35.5 kHz */
  70.     0x5F + 0x100,        /* adds 1024x768 interlaced */
  71. /* type 3, 38 kHz */
  72.     0x15F + 0x20 + 0x80,    /* adds 640x480 @ 72 Hz, 800x600 @ 60 Hz */
  73. /* type 4, 48.3 kHz */
  74.     0x1FF + 0x200 + 0x400,    /* adds 800x600 @ 72 Hz, 1024x768 @ 60 Hz */
  75. /* type 5, 56.0 kHz */
  76.     0x7FF + 0x800 + 0x1000,    /* adds 1024x768 @ 70 Hz, 1280x1024 interl. */
  77. /* type 6, 60 kHz */
  78.     0x1FFF            /* no 1024x768 72 Hz timing yet */
  79. };
  80.  
  81.  
  82. /*
  83.  * The getmodetiming function looks up a mode in the standard mode
  84.  * timings, choosing the mode with the highest dot clock that matches
  85.  * the requested svgalib mode, and is supported by the hardware
  86.  * (card limits, and monitor type). cardlimits points to a structure
  87.  * of type CardSpecs that describes the dot clocks the card supports
  88.  * at different depths. Returns non-zero if no mode is found.
  89.  */
  90.  
  91. /*
  92.  * findclock is an auxilliary function that checks if a close enough
  93.  * pixel clock is provided by the card. Returns clock number if
  94.  * succesful (a special number if a programmable clock must be used), -1
  95.  * otherwise.
  96.  */
  97.  
  98. /*
  99.  * Clock allowance in 1/1000ths. 10 (1%) corresponds to a 250 kHz
  100.  * deviation at 25 MHz, 1 MHz at 100 MHz
  101.  */
  102. #define CLOCK_ALLOWANCE 10
  103.  
  104. #define PROGRAMMABLE_CLOCK_MAGIC_NUMBER 0x1234
  105.  
  106. static int findclock( int clock, CardSpecs *cardspecs ) {
  107.     int i;
  108.     /* Find a clock that is close enough. */
  109.     for (i = 0; i < cardspecs->nClocks; i++) {
  110.         int diff;
  111.         diff = cardspecs->clocks[i] - clock;
  112.         if (diff < 0)
  113.             diff = -diff;
  114.         if (diff * 1000 / clock < CLOCK_ALLOWANCE)
  115.             return i;
  116.     }
  117.     /* Try programmable clocks if available. */
  118.     if (cardspecs->flags & CLOCK_PROGRAMMABLE) {
  119.         int diff;
  120.         diff = cardspecs->matchProgrammableClock(clock) - clock;
  121.         if (diff < 0)
  122.             diff = -diff;
  123.         if (diff * 1000 / clock < CLOCK_ALLOWANCE)
  124.             return PROGRAMMABLE_CLOCK_MAGIC_NUMBER;
  125.     }
  126.     /* No close enough clock found. */
  127.     return -1;
  128. }
  129.  
  130. int getmodetiming( ModeTiming *modetiming, ModeInfo *modeinfo,
  131. CardSpecs *cardspecs ) {
  132.     int maxclock, bestclock, besttiming, desiredclock;
  133.     int i;
  134.  
  135.     /* Get the maximum pixel clock for the depth of the requested mode. */
  136.     if (modeinfo->bitsPerPixel == 4)
  137.         maxclock = cardspecs->maxPixelClock4bpp;
  138.     else
  139.     if (modeinfo->bitsPerPixel == 8)
  140.         maxclock = cardspecs->maxPixelClock8bpp;
  141.     else
  142.     if (modeinfo->bitsPerPixel == 16) {
  143.         if ((cardspecs->flags & NO_RGB16_565)
  144.         && modeinfo->greenWeight == 6)
  145.             return 1;    /* No 5-6-5 RGB. */
  146.         maxclock = cardspecs->maxPixelClock16bpp;
  147.     }
  148.     else
  149.     if (modeinfo->bitsPerPixel == 24)
  150.         maxclock = cardspecs->maxPixelClock24bpp;
  151.     else
  152.     if (modeinfo->bitsPerPixel == 32)
  153.         maxclock = cardspecs->maxPixelClock32bpp;
  154.     else
  155.         maxclock = 0;
  156.  
  157.     /*
  158.      * bestclock is the highest pixel clock found for the resolution
  159.      * in the mode timings, within the spec of the card and
  160.      * monitor.
  161.      */
  162.     bestclock = 0;
  163.  
  164.     /* Search the standard timings for the best matching mode. */
  165.     for (i = 0; i < NUMBER_OF_STANDARD_MODES; i++)
  166.         if (standard_timings[i].HDisplay == modeinfo->width
  167.         && (standard_timings[i].VDisplay == modeinfo->height
  168.             || ((standard_timings[i].flags & DOUBLESCAN)
  169.                   && standard_timings[i].VDisplay ==
  170.                   modeinfo->height * 2))
  171.         && TIMING_WITHIN_MONITOR_SPEC(i)
  172.         && standard_timings[i].pixelClock <= maxclock
  173.         && standard_timings[i].pixelClock > bestclock
  174.         && cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  175.             standard_timings[i].pixelClock,
  176.             standard_timings[i].HTotal)
  177.             <= cardspecs->maxHorizontalCrtc
  178.         /* Find the clock (possibly scaled by mapClock). */
  179.         && findclock(cardspecs->mapClock(modeinfo->bitsPerPixel,
  180.             standard_timings[i].pixelClock), cardspecs) != -1
  181.         ) {
  182.             bestclock = standard_timings[i].pixelClock;
  183.             besttiming = i;
  184.         }
  185.     if (bestclock == 0)
  186.         return 1;    /* Unsuccesful. */
  187.  
  188.     /*
  189.      * Copy the selected timings into the result, which may
  190.      * be adjusted for the chipset.
  191.      */
  192.  
  193.     modetiming->flags = standard_timings[besttiming].flags;
  194.     modetiming->pixelClock = bestclock;    /* Formal clock. */
  195.  
  196.     /*
  197.      * We know a close enough clock is available; the following is the
  198.      * exact clock that fits the mode. This is probably different
  199.      * from the best matching clock that will be programmed.
  200.      */
  201.     desiredclock = cardspecs->mapClock(modeinfo->bitsPerPixel,
  202.         standard_timings[besttiming].pixelClock),
  203.  
  204.     /* Fill in the best-matching clock that will be programmed. */
  205.     modetiming->selectedClockNo = findclock(desiredclock, cardspecs);
  206.     if (modetiming->selectedClockNo == PROGRAMMABLE_CLOCK_MAGIC_NUMBER) {
  207.         modetiming->programmedClock =
  208.             cardspecs->matchProgrammableClock(desiredclock);
  209.         modetiming->flags |= USEPROGRCLOCK;
  210.     }
  211.     else
  212.         modetiming->programmedClock = cardspecs->clocks[
  213.             modetiming->selectedClockNo];
  214.     modetiming->HDisplay = standard_timings[besttiming].HDisplay;
  215.     modetiming->HSyncStart = standard_timings[besttiming].HSyncStart;
  216.     modetiming->HSyncEnd = standard_timings[besttiming].HSyncEnd;
  217.     modetiming->HTotal = standard_timings[besttiming].HTotal;
  218.     if (cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  219.             modetiming->programmedClock,
  220.             standard_timings[besttiming].HTotal)
  221.     != standard_timings[besttiming].HTotal) {
  222.         /* Horizontal CRTC timings are scaled in some way. */
  223.         modetiming->CrtcHDisplay =
  224.             cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  225.                 modetiming->programmedClock,
  226.                 standard_timings[besttiming].HDisplay);
  227.         modetiming->CrtcHSyncStart =
  228.             cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  229.                 modetiming->programmedClock,
  230.                 standard_timings[besttiming].HSyncStart);
  231.         modetiming->CrtcHSyncEnd =
  232.             cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  233.                 modetiming->programmedClock,
  234.                 standard_timings[besttiming].HSyncEnd);
  235.         modetiming->CrtcHTotal =
  236.             cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
  237.                 modetiming->programmedClock,
  238.                 standard_timings[besttiming].HTotal);
  239.         modetiming->flags |= HADJUSTED;
  240.     }
  241.     else {
  242.         modetiming->CrtcHDisplay = standard_timings[besttiming].HDisplay;
  243.         modetiming->CrtcHSyncStart = standard_timings[besttiming].HSyncStart;
  244.         modetiming->CrtcHSyncEnd = standard_timings[besttiming].HSyncEnd;
  245.         modetiming->CrtcHTotal = standard_timings[besttiming].HTotal;
  246.     }
  247.     modetiming->VDisplay = standard_timings[besttiming].VDisplay;
  248.     modetiming->CrtcVDisplay = standard_timings[besttiming].VDisplay;
  249.     modetiming->VSyncStart = standard_timings[besttiming].VSyncStart;
  250.     modetiming->CrtcVSyncStart = standard_timings[besttiming].VSyncStart;
  251.     modetiming->VSyncEnd = standard_timings[besttiming].VSyncEnd;
  252.     modetiming->CrtcVSyncEnd = standard_timings[besttiming].VSyncEnd;
  253.     modetiming->VTotal = standard_timings[besttiming].VTotal;
  254.     modetiming->CrtcVTotal = standard_timings[besttiming].VTotal;
  255.     if (((modetiming->flags & INTERLACED)
  256.     && (cardspecs->flags & INTERLACE_DIVIDE_VERT))
  257.     || (modetiming->VTotal >= 1024
  258.     && (cardspecs->flags & GREATER_1024_DIVIDE_VERT))) {
  259.         /*
  260.          * Card requires vertical CRTC timing to be halved for
  261.          * interlaced modes, or for all modes with vertical
  262.          * timing >= 1024.
  263.          */
  264.         modetiming->CrtcVDisplay /= 2;
  265.         modetiming->CrtcVSyncStart /= 2;
  266.         modetiming->CrtcVSyncEnd /= 2;
  267.         modetiming->CrtcVTotal /= 2;
  268.         modetiming->flags |= VADJUSTED;
  269.     }
  270.     return 0;    /* Succesful. */
  271. }
  272.