summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2006-04-14 13:39:17 -0500
committerEric Anholt <anholt@FreeBSD.org>2006-04-14 13:39:17 -0500
commite5f741d634393812062ebd185e7e0a7b7706b3b9 (patch)
treeda2b9db058e99bc4720bf513c0386d1d982c0e2d
parente275ec82571c182bb8cd7296cfb50f989c6fa9e1 (diff)
Add insertion of VESA established modes from EDID information.
-rw-r--r--src/i830_modes.c130
1 files changed, 124 insertions, 6 deletions
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7d517202..32a923bd 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -31,11 +31,31 @@
#include <stdio.h>
#include <string.h>
+#include <math.h>
#include "xf86.h"
#include "i830.h"
#include "i830_modes.h"
+/** @file
+ * This file deals with creating lists of valid modes for an output device.
+ *
+ * It attempts to always have valid modes for the output in the list. This is
+ * unlike xf86Mode.c, which dumps all the modes it can find into the list and
+ * then validates them and then prunes them out later.
+ */
+
+static int
+i830GetModeListLen(DisplayModePtr first)
+{
+ DisplayModePtr mode;
+ int i = 0;
+
+ for (mode = first; mode != NULL && mode != first; mode = mode->next)
+ i++;
+ return i;
+}
+
/**
* i830SetModeToPanelParameters() fills a mode pointer with timing information
* from the panel.
@@ -69,7 +89,6 @@ i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode)
last = new; \
if (!first) \
first = new; \
- count++; \
} while (0)
/**
@@ -107,7 +126,6 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
DisplayModePtr new = NULL;
DisplayModePtr first = NULL;
DisplayModePtr p;
- int count = 0;
int i, width, height;
/* We have a flat panel connected to the primary display, and we
@@ -190,13 +208,73 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Total number of valid FP mode(s) found: %d\n", count);
+ "Total number of valid FP mode(s) found: %d\n",
+ i830GetModeListLen(first));
return first;
}
+/* Pulled from xf86Mode.c since it was static there. Used for finding
+ * the established modes from the mode list.
+ */
+static double
+ModeVRefresh(DisplayModePtr mode)
+{
+ double refresh = 0.0;
+
+ if (mode->VRefresh > 0.0)
+ refresh = mode->VRefresh;
+ else if (mode->HTotal > 0 && mode->VTotal > 0) {
+ refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
+ if (mode->Flags & V_INTERLACE)
+ refresh *= 2.0;
+ if (mode->Flags & V_DBLSCAN)
+ refresh /= 2.0;
+ if (mode->VScan > 1)
+ refresh /= (float)(mode->VScan);
+ }
+ return refresh;
+}
+
+/* From xf86DefMode{s,Set}.c */
+extern DisplayModeRec xf86DefaultModes[];
+
+static void
+i830AddEstablishedMode(ScrnInfoPtr pScrn, int x, int y, int refresh,
+ DisplayModePtr *first, DisplayModePtr *last)
+{
+ DisplayModePtr mode, new;
+
+ for (mode = xf86DefaultModes; mode->name != NULL; mode++) {
+ float mode_refresh;
+
+ if (mode->HDisplay != x || mode->VDisplay != y)
+ continue;
+
+ mode_refresh = ModeVRefresh(mode);
+ /* Select the default mode that's within 5% of the refresh rate we're
+ * looking for. Should get the right one every time.
+ */
+ if (fabs(mode_refresh - refresh) >= (refresh * .05))
+ continue;
+
+ new = xnfcalloc(1, sizeof(DisplayModeRec));
+ memcpy(new, mode, sizeof(DisplayModeRec));
+ new->name = strdup(mode->name);
+
+ new->next = NULL;
+ new->prev = *last;
+
+ if (*last)
+ (*last)->next = new;
+ *last = new;
+ if (!first)
+ *first = new;
+ }
+}
+
/**
- *EDID mode validation routine for using panel fitting.
+ * EDID mode validation routine for using panel fitting.
*
* Modes in the list will be in the order of user-selected modes, followed by
* EDID modes from the given monitor. For now, it's only pulling out one set
@@ -211,10 +289,14 @@ i830ValidateEDIDModes(ScrnInfoPtr pScrn, xf86MonPtr MonInfo)
DisplayModePtr last = NULL;
DisplayModePtr new = NULL;
DisplayModePtr first = NULL;
- int i, count = 0;
+ int i;
char stmp[32];
struct detailed_timings *dt;
+ /* XXX: Need to insert user-requested modes first here if we can. It's
+ * straight EDID at the moment.
+ */
+
for (i = 0; i < DET_TIMINGS; i++) {
switch (MonInfo->det_mon[i].type) {
case DT:
@@ -232,6 +314,7 @@ i830ValidateEDIDModes(ScrnInfoPtr pScrn, xf86MonPtr MonInfo)
new->VSyncStart = dt->v_active + dt->v_sync_off;
new->VSyncEnd = new->VSyncStart + dt->v_sync_width;
new->Clock = dt->clock;
+ /* XXX: Deal with syncing */
new->type |= M_T_DEFAULT;
@@ -240,6 +323,40 @@ i830ValidateEDIDModes(ScrnInfoPtr pScrn, xf86MonPtr MonInfo)
break;
}
}
+ if (MonInfo->timings1.t1 & 0x80)
+ i830AddEstablishedMode(pScrn, 720, 400, 70, &first, &last);
+ if (MonInfo->timings1.t1 & 0x40)
+ i830AddEstablishedMode(pScrn, 720, 400, 88, &first, &last);
+ if (MonInfo->timings1.t1 & 0x20)
+ i830AddEstablishedMode(pScrn, 640, 480, 60, &first, &last);
+ if (MonInfo->timings1.t1 & 0x10)
+ i830AddEstablishedMode(pScrn, 640, 480, 67, &first, &last);
+ if (MonInfo->timings1.t1 & 0x08)
+ i830AddEstablishedMode(pScrn, 640, 480, 72, &first, &last);
+ if (MonInfo->timings1.t1 & 0x04)
+ i830AddEstablishedMode(pScrn, 640, 480, 75, &first, &last);
+ if (MonInfo->timings1.t1 & 0x02)
+ i830AddEstablishedMode(pScrn, 800, 600, 56, &first, &last);
+ if (MonInfo->timings1.t1 & 0x01)
+ i830AddEstablishedMode(pScrn, 800, 600, 60, &first, &last);
+ if (MonInfo->timings1.t2 & 0x80)
+ i830AddEstablishedMode(pScrn, 800, 600, 72, &first, &last);
+ if (MonInfo->timings1.t2 & 0x40)
+ i830AddEstablishedMode(pScrn, 800, 600, 75, &first, &last);
+ if (MonInfo->timings1.t2 & 0x20)
+ i830AddEstablishedMode(pScrn, 832, 624, 75, &first, &last);
+ if (MonInfo->timings1.t2 & 0x10)
+ i830AddEstablishedMode(pScrn, 1024, 768, 87, &first, &last);
+ if (MonInfo->timings1.t2 & 0x08)
+ i830AddEstablishedMode(pScrn, 1024, 768, 60, &first, &last);
+ if (MonInfo->timings1.t2 & 0x04)
+ i830AddEstablishedMode(pScrn, 1024, 768, 70, &first, &last);
+ if (MonInfo->timings1.t2 & 0x02)
+ i830AddEstablishedMode(pScrn, 1024, 768, 75, &first, &last);
+ if (MonInfo->timings1.t2 & 0x01)
+ i830AddEstablishedMode(pScrn, 1280, 1024, 75, &first, &last);
+ if (MonInfo->timings1.t_manu & 0x80)
+ i830AddEstablishedMode(pScrn, 1152, 870, 75, &first, &last);
/* Close the doubly-linked mode list */
if (last) {
@@ -248,7 +365,8 @@ i830ValidateEDIDModes(ScrnInfoPtr pScrn, xf86MonPtr MonInfo)
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Total number of valid EDID mode(s) found: %d\n", count);
+ "Total number of valid EDID mode(s) found: %d\n",
+ i830GetModeListLen(first));
return first;
}