home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * Generic mode timing module.
- */
-
- #include "timing.h" /* Types. */
-
- #include "libvga.h" /* for __svgalib_infotable (remove me) */
- #include "driver.h" /* for __svgalib_monitortype (remove me) */
-
- /* Standard mode timings. */
-
- MonitorModeTiming standard_timings[] = {
- /* 320x200 @ 70 Hz, 31.5 kHz hsync */
- { 12588, 320, 336, 384, 400, 400, 409, 411, 450, DOUBLESCAN },
- /* 320x240 @ 60 Hz, 31.5 kHz hsync */
- { 12588, 320, 336, 384, 400, 480, 491, 493, 525, DOUBLESCAN },
- /* 320x240 @ 72 Hz, 36.5 kHz hsync */
- { 15750, 320, 336, 384, 400, 480, 488, 491, 521, DOUBLESCAN },
- /* 640x400 at 70 Hz, 31.5 kHz hsync */
- { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0 },
- /* 640x480 at 60 Hz, 31.5 kHz hsync */
- { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0 },
- /* 640x480 at 72 Hz, 36.5 kHz hsync */
- { 31500, 640, 680, 720, 864, 480, 488, 491, 521, 0 },
- /* 800x600 at 56 Hz, 35.15 kHz hsync */
- { 36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0 },
- /* 800x600 at 60 Hz, 37.8 kHz hsync */
- { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, PHSYNC | PVSYNC },
- /* 1024x768 at 87 Hz interlaced, 35.5 kHz hsync */
- { 44900, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED },
- /* 800x600 at 72 Hz, 48.0 kHz hsync */
- { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, PHSYNC | PVSYNC },
- /* 1024x768 at 60 Hz, 48.4 kHz hsync */
- { 65000, 1024, 1032, 1176, 1344, 768, 771, 777, 806, NHSYNC | NVSYNC },
- /* 1024x768 at 70 Hz, 56.6 kHz hsync */
- { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, NHSYNC | NVSYNC },
- /* 1280x1024 at 87 Hz interlaced, 51 kHz hsync */
- { 80000, 1280, 1296, 1512, 1568, 1024, 1025, 1037, 1165, INTERLACED },
- /* 1024x768 at 76 Hz, 62.5 kHz hsync */
- { 85000, 1024, 1032, 1152, 1360, 768, 784, 787, 823, 0 },
- /* 1280x1024 at 60 Hz, ? kHz hsync */
- { 110000, 1280, 1328, 1512, 1712, 1024, 1025, 1028, 1054, 0 },
- /* 1280x1024 at 70 Hz, ? kHz hsync */
- { 135000, 1280, 1312, 1456, 1712, 1024, 1027, 1030, 1064, 0 }
- };
-
- #define NUMBER_OF_STANDARD_MODES \
- (sizeof(standard_timings) / sizeof(standard_timings[0]))
-
- /*
- * Monitor spec checking is done with a fixed table, rather than
- * calculations. The monitor types are defined in terms of the supported
- * mode timings.
- *
- * This should be extended into a configuration file with mode timings,
- * which are checked against monitor specs with calculations.
- */
-
- #define TIMING_WITHIN_MONITOR_SPEC(i) \
- (timing_within_monitor_spec[__svgalib_monitortype] & (1 << i))
-
- unsigned short timing_within_monitor_spec[7] = {
- /* type 0, 31.5 kHz */
- 0x07 + /* doublescan modes */
- 0x08 + 0x10, /* 640x400 and 640x480 at 60 Hz */
- /* type 1, 35.2 kHz */
- 0x1F + 0x40, /* adds 800x600 @ 56 Hz */
- /* type 2, 35.5 kHz */
- 0x5F + 0x100, /* adds 1024x768 interlaced */
- /* type 3, 38 kHz */
- 0x15F + 0x20 + 0x80, /* adds 640x480 @ 72 Hz, 800x600 @ 60 Hz */
- /* type 4, 48.3 kHz */
- 0x1FF + 0x200 + 0x400, /* adds 800x600 @ 72 Hz, 1024x768 @ 60 Hz */
- /* type 5, 56.0 kHz */
- 0x7FF + 0x800 + 0x1000, /* adds 1024x768 @ 70 Hz, 1280x1024 interl. */
- /* type 6, 60 kHz */
- 0x1FFF /* no 1024x768 72 Hz timing yet */
- };
-
-
- /*
- * The getmodetiming function looks up a mode in the standard mode
- * timings, choosing the mode with the highest dot clock that matches
- * the requested svgalib mode, and is supported by the hardware
- * (card limits, and monitor type). cardlimits points to a structure
- * of type CardSpecs that describes the dot clocks the card supports
- * at different depths. Returns non-zero if no mode is found.
- */
-
- /*
- * findclock is an auxilliary function that checks if a close enough
- * pixel clock is provided by the card. Returns clock number if
- * succesful (a special number if a programmable clock must be used), -1
- * otherwise.
- */
-
- /*
- * Clock allowance in 1/1000ths. 10 (1%) corresponds to a 250 kHz
- * deviation at 25 MHz, 1 MHz at 100 MHz
- */
- #define CLOCK_ALLOWANCE 10
-
- #define PROGRAMMABLE_CLOCK_MAGIC_NUMBER 0x1234
-
- static int findclock( int clock, CardSpecs *cardspecs ) {
- int i;
- /* Find a clock that is close enough. */
- for (i = 0; i < cardspecs->nClocks; i++) {
- int diff;
- diff = cardspecs->clocks[i] - clock;
- if (diff < 0)
- diff = -diff;
- if (diff * 1000 / clock < CLOCK_ALLOWANCE)
- return i;
- }
- /* Try programmable clocks if available. */
- if (cardspecs->flags & CLOCK_PROGRAMMABLE) {
- int diff;
- diff = cardspecs->matchProgrammableClock(clock) - clock;
- if (diff < 0)
- diff = -diff;
- if (diff * 1000 / clock < CLOCK_ALLOWANCE)
- return PROGRAMMABLE_CLOCK_MAGIC_NUMBER;
- }
- /* No close enough clock found. */
- return -1;
- }
-
- int getmodetiming( ModeTiming *modetiming, ModeInfo *modeinfo,
- CardSpecs *cardspecs ) {
- int maxclock, bestclock, besttiming, desiredclock;
- int i;
-
- /* Get the maximum pixel clock for the depth of the requested mode. */
- if (modeinfo->bitsPerPixel == 4)
- maxclock = cardspecs->maxPixelClock4bpp;
- else
- if (modeinfo->bitsPerPixel == 8)
- maxclock = cardspecs->maxPixelClock8bpp;
- else
- if (modeinfo->bitsPerPixel == 16) {
- if ((cardspecs->flags & NO_RGB16_565)
- && modeinfo->greenWeight == 6)
- return 1; /* No 5-6-5 RGB. */
- maxclock = cardspecs->maxPixelClock16bpp;
- }
- else
- if (modeinfo->bitsPerPixel == 24)
- maxclock = cardspecs->maxPixelClock24bpp;
- else
- if (modeinfo->bitsPerPixel == 32)
- maxclock = cardspecs->maxPixelClock32bpp;
- else
- maxclock = 0;
-
- /*
- * bestclock is the highest pixel clock found for the resolution
- * in the mode timings, within the spec of the card and
- * monitor.
- */
- bestclock = 0;
-
- /* Search the standard timings for the best matching mode. */
- for (i = 0; i < NUMBER_OF_STANDARD_MODES; i++)
- if (standard_timings[i].HDisplay == modeinfo->width
- && (standard_timings[i].VDisplay == modeinfo->height
- || ((standard_timings[i].flags & DOUBLESCAN)
- && standard_timings[i].VDisplay ==
- modeinfo->height * 2))
- && TIMING_WITHIN_MONITOR_SPEC(i)
- && standard_timings[i].pixelClock <= maxclock
- && standard_timings[i].pixelClock > bestclock
- && cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- standard_timings[i].pixelClock,
- standard_timings[i].HTotal)
- <= cardspecs->maxHorizontalCrtc
- /* Find the clock (possibly scaled by mapClock). */
- && findclock(cardspecs->mapClock(modeinfo->bitsPerPixel,
- standard_timings[i].pixelClock), cardspecs) != -1
- ) {
- bestclock = standard_timings[i].pixelClock;
- besttiming = i;
- }
- if (bestclock == 0)
- return 1; /* Unsuccesful. */
-
- /*
- * Copy the selected timings into the result, which may
- * be adjusted for the chipset.
- */
-
- modetiming->flags = standard_timings[besttiming].flags;
- modetiming->pixelClock = bestclock; /* Formal clock. */
-
- /*
- * We know a close enough clock is available; the following is the
- * exact clock that fits the mode. This is probably different
- * from the best matching clock that will be programmed.
- */
- desiredclock = cardspecs->mapClock(modeinfo->bitsPerPixel,
- standard_timings[besttiming].pixelClock),
-
- /* Fill in the best-matching clock that will be programmed. */
- modetiming->selectedClockNo = findclock(desiredclock, cardspecs);
- if (modetiming->selectedClockNo == PROGRAMMABLE_CLOCK_MAGIC_NUMBER) {
- modetiming->programmedClock =
- cardspecs->matchProgrammableClock(desiredclock);
- modetiming->flags |= USEPROGRCLOCK;
- }
- else
- modetiming->programmedClock = cardspecs->clocks[
- modetiming->selectedClockNo];
- modetiming->HDisplay = standard_timings[besttiming].HDisplay;
- modetiming->HSyncStart = standard_timings[besttiming].HSyncStart;
- modetiming->HSyncEnd = standard_timings[besttiming].HSyncEnd;
- modetiming->HTotal = standard_timings[besttiming].HTotal;
- if (cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- modetiming->programmedClock,
- standard_timings[besttiming].HTotal)
- != standard_timings[besttiming].HTotal) {
- /* Horizontal CRTC timings are scaled in some way. */
- modetiming->CrtcHDisplay =
- cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- modetiming->programmedClock,
- standard_timings[besttiming].HDisplay);
- modetiming->CrtcHSyncStart =
- cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- modetiming->programmedClock,
- standard_timings[besttiming].HSyncStart);
- modetiming->CrtcHSyncEnd =
- cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- modetiming->programmedClock,
- standard_timings[besttiming].HSyncEnd);
- modetiming->CrtcHTotal =
- cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
- modetiming->programmedClock,
- standard_timings[besttiming].HTotal);
- modetiming->flags |= HADJUSTED;
- }
- else {
- modetiming->CrtcHDisplay = standard_timings[besttiming].HDisplay;
- modetiming->CrtcHSyncStart = standard_timings[besttiming].HSyncStart;
- modetiming->CrtcHSyncEnd = standard_timings[besttiming].HSyncEnd;
- modetiming->CrtcHTotal = standard_timings[besttiming].HTotal;
- }
- modetiming->VDisplay = standard_timings[besttiming].VDisplay;
- modetiming->CrtcVDisplay = standard_timings[besttiming].VDisplay;
- modetiming->VSyncStart = standard_timings[besttiming].VSyncStart;
- modetiming->CrtcVSyncStart = standard_timings[besttiming].VSyncStart;
- modetiming->VSyncEnd = standard_timings[besttiming].VSyncEnd;
- modetiming->CrtcVSyncEnd = standard_timings[besttiming].VSyncEnd;
- modetiming->VTotal = standard_timings[besttiming].VTotal;
- modetiming->CrtcVTotal = standard_timings[besttiming].VTotal;
- if (((modetiming->flags & INTERLACED)
- && (cardspecs->flags & INTERLACE_DIVIDE_VERT))
- || (modetiming->VTotal >= 1024
- && (cardspecs->flags & GREATER_1024_DIVIDE_VERT))) {
- /*
- * Card requires vertical CRTC timing to be halved for
- * interlaced modes, or for all modes with vertical
- * timing >= 1024.
- */
- modetiming->CrtcVDisplay /= 2;
- modetiming->CrtcVSyncStart /= 2;
- modetiming->CrtcVSyncEnd /= 2;
- modetiming->CrtcVTotal /= 2;
- modetiming->flags |= VADJUSTED;
- }
- return 0; /* Succesful. */
- }
-