summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@fairlite.demon.co.uk>2005-03-15 11:32:10 +0000
committerAlan Hourihane <alanh@fairlite.demon.co.uk>2005-03-15 11:32:10 +0000
commiteb8b5df739e7be4509423c2bf757a7df35ce02f6 (patch)
treebfa49a8aac6700b5ea21f576b47bea4a9e2b7c92
parent49dcbacf7fa7f29d18c18eec7e2f99e859bf4c7e (diff)
downloadxf86-video-intel-eb8b5df739e7be4509423c2bf757a7df35ce02f6.tar.gz
xf86-video-intel-eb8b5df739e7be4509423c2bf757a7df35ce02f6.tar.bz2
xf86-video-intel-eb8b5df739e7be4509423c2bf757a7df35ce02f6.zip
Enforce DDC monitor ranges usage if we have them and reject bad
modes. Use NoDDC option to override DDC timings. We currently only use DS_RANGES, but could use other DDC information, as does the common layer, to deduce the h/v ranges.
-rw-r--r--src/i830_driver.c159
-rw-r--r--src/i830_modes.c2
2 files changed, 103 insertions, 58 deletions
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f54179318..acfd57d53 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1557,6 +1557,70 @@ PreInitCleanup(ScrnInfoPtr pScrn)
}
static int
+I830UseDDC(ScrnInfoPtr pScrn)
+{
+ xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
+ struct detailed_monitor_section* detMon;
+ struct monitor_ranges *mon_range = NULL;
+ Bool ret = FALSE;
+ int i;
+
+ /* Now change the hsync/vrefresh values of the current monitor to
+ * match those of DDC */
+ for (i = 0; i < 4; i++) {
+ detMon = &DDC->det_mon[i];
+ if(detMon->type == DS_RANGES)
+ mon_range = &detMon->section.ranges;
+ }
+
+ if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
+ mon_range->min_v == 0 || mon_range->max_v == 0)
+ return FALSE; /* bad ddc */
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n",
+ mon_range->min_h, mon_range->max_h);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tVertRefresh %d-%d\n",
+ mon_range->min_v, mon_range->max_v);
+#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
+ if (pScrn->monitor->nHsync > 0) {
+ for (i = 0; i < pScrn->monitor->nHsync; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
+ pScrn->monitor->hsync[i].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
+ pScrn->monitor->hsync[i].hi) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "config file hsync range %g-%gkHz not within DDC "
+ "hsync range %d-%dkHz\n",
+ pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
+ mon_range->min_h, mon_range->max_h);
+ }
+ pScrn->monitor->hsync[i].lo = mon_range->min_h;
+ pScrn->monitor->hsync[i].hi = mon_range->max_h;
+ }
+ }
+
+ if (pScrn->monitor->nVrefresh > 0) {
+ for (i=0; i<pScrn->monitor->nVrefresh; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
+ pScrn->monitor->vrefresh[i].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
+ pScrn->monitor->vrefresh[i].hi) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "config file vrefresh range %g-%gHz not within DDC "
+ "vrefresh range %d-%dHz\n",
+ pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
+ mon_range->min_v, mon_range->max_v);
+ }
+ pScrn->monitor->vrefresh[i].lo = mon_range->min_v;
+ pScrn->monitor->vrefresh[i].hi = mon_range->max_v;
+ }
+ }
+
+ return mon_range->max_clock;
+}
+
+static int
GetBIOSPipe(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
@@ -1653,7 +1717,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
int flags24;
int defmon = 0;
int i, n;
+ int DDCclock = 0;
char *s;
+ DisplayModePtr p, pMon;
pointer pDDCModule, pVBEModule;
Bool enable;
const char *chipname;
@@ -2583,6 +2649,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
xf86UnloadSubModule(pDDCModule);
+ DDCclock = I830UseDDC(pScrn);
+
/* XXX Move this to a header. */
#define VIDEO_BIOS_SCRATCH 0x18
@@ -2739,6 +2807,35 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
+ /* Only use this if we've got DDC available */
+ if (DDCclock > 0) {
+ p = pScrn->modes;
+ if (p == NULL)
+ return FALSE;
+ do {
+ int Clock = 100000000; /* incredible value */
+
+ for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
+ if ((pMon->HDisplay != p->HDisplay) ||
+ (pMon->VDisplay != p->VDisplay) ||
+ (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+
+ /* Find lowest supported Clock for this resolution */
+ if (Clock > pMon->Clock)
+ Clock = pMon->Clock;
+ }
+
+ if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
+ ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
+ p->name, pScrn->monitor->id,
+ Clock/1000.0, DDCclock);
+ p->status = MODE_BAD;
+ }
+ p = p->next;
+ } while (p != NULL && p != pScrn->modes);
+ }
+
xf86PruneDriverModes(pScrn);
pScrn->currentMode = pScrn->modes;
@@ -4582,9 +4679,8 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
pointer pDDCModule;
DisplayModePtr p, pMon;
xf86MonPtr DDC;
- struct detailed_monitor_section* detMon;
int i, memsize;
- struct monitor_ranges *mon_range = NULL;
+ int DDCclock = 0;
int displayWidth = pScrn->displayWidth;
int curHDisplay = pScrn->currentMode->HDisplay;
int curVDisplay = pScrn->currentMode->VDisplay;
@@ -4607,56 +4703,8 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
/* No DDC, so get out of here, and continue to use the current settings */
return FALSE;
- DDC = (xf86MonPtr)(pScrn->monitor->DDC);
-
- /* Now change the hsync/vrefresh values of the current monitor to
- * match those of DDC */
- for (i = 0; i < 4; i++) {
- detMon = &DDC->det_mon[i];
- if(detMon->type == DS_RANGES)
- mon_range = &detMon->section.ranges;
- }
-
- if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
- mon_range->min_v == 0 || mon_range->max_v == 0)
- return FALSE; /* bad ddc */
-
- if (mon_range) {
-#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
- if (pScrn->monitor->nHsync > 0) {
- for (i = 0; i < pScrn->monitor->nHsync; i++) {
- if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
- pScrn->monitor->hsync[i].lo ||
- (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
- pScrn->monitor->hsync[i].hi) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "config file hsync range %g-%gkHz not within DDC "
- "hsync range %d-%dkHz\n",
- pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
- mon_range->min_h, mon_range->max_h);
- }
- pScrn->monitor->hsync[i].lo = mon_range->min_h;
- pScrn->monitor->hsync[i].hi = mon_range->max_h;
- }
- }
-
- if (pScrn->monitor->nVrefresh > 0) {
- for (i=0; i<pScrn->monitor->nVrefresh; i++) {
- if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
- pScrn->monitor->vrefresh[i].lo ||
- (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
- pScrn->monitor->vrefresh[i].hi) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "config file vrefresh range %g-%gHz not within DDC "
- "vrefresh range %d-%dHz\n",
- pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
- mon_range->min_v, mon_range->max_v);
- }
- pScrn->monitor->vrefresh[i].lo = mon_range->min_v;
- pScrn->monitor->vrefresh[i].hi = mon_range->max_v;
- }
- }
- } /* if (mon_range) */
+ if (!(DDCclock = I830UseDDC(pScrn)))
+ return FALSE;
/* Revalidate the modes */
@@ -4708,13 +4756,10 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
Clock = pMon->Clock;
}
- if (mon_range->max_clock < 2550 &&
- Clock / 1000.0 > mon_range->max_clock) {
-#if 0
+ if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
p->name, pScrn->monitor->id,
- Clock/1000.0, mon_range->max_clock);
-#endif
+ Clock/1000.0, DDCclock);
p->status = MODE_BAD;
}
p = p->next;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 97ce45a5c..fcbaf307f 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -344,7 +344,7 @@ I830GetGTF (int h_pixels, int v_lines, float freq,
m->HSync = h_freq;
m->VRefresh = freq;
- sprintf(modename, "%dx%d", m->HDisplay,m->VDisplay);
+ snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
m->name = xnfstrdup(modename);
return (m);