diff options
author | Luc Verhaegen <libv@skynet.be> | 2006-09-14 18:30:36 -0400 |
---|---|---|
committer | Adam Jackson <ajax@benzedrine.nwnk.net> | 2006-09-14 18:30:36 -0400 |
commit | 511c60bc7399b07c267d686a969880e5ec92408a (patch) | |
tree | 593f1b3ffaecd30940c6b58434db1520fdddfe9d | |
parent | 05231e336db8f959c15dda518641976f061df1a6 (diff) |
Bug #5386: Synthesize modelines from EDID data.
-rw-r--r-- | hw/xfree86/common/xf86Mode.c | 187 | ||||
-rw-r--r-- | hw/xfree86/ddc/ddcProperty.c | 502 | ||||
-rw-r--r-- | hw/xfree86/ddc/xf86DDC.h | 3 |
3 files changed, 378 insertions, 314 deletions
diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c index cd57e9916..ff045835a 100644 --- a/hw/xfree86/common/xf86Mode.c +++ b/hw/xfree86/common/xf86Mode.c @@ -45,7 +45,6 @@ #include "globals.h" #include "xf86.h" #include "xf86Priv.h" -#include "xf86DDC.h" static void printModeRejectMessage(int index, DisplayModePtr p, int status) @@ -766,31 +765,6 @@ xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) mode, mode->name, monitor, monitor->id); #endif - if (monitor->DDC) { - xf86MonPtr DDC = (xf86MonPtr)(monitor->DDC); - struct detailed_monitor_section* detMon; - struct monitor_ranges *mon_range; - int i; - - mon_range = NULL; - for (i = 0; i < 4; i++) { - detMon = &DDC->det_mon[i]; - if(detMon->type == DS_RANGES) { - mon_range = &detMon->section.ranges; - } - } - if (mon_range) { - /* mode->Clock in kHz, DDC in MHz */ - if (mon_range->max_clock < 2550 && - mode->Clock / 1000.0 > mon_range->max_clock) { - xf86Msg(X_WARNING, - "(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", - mode->name, monitor->id, - mode->Clock/1000.0, mon_range->max_clock); - } - } - } - /* Some basic mode validity checks */ if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) @@ -1267,7 +1241,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, PixmapFormatRec *BankFormat; ClockRangePtr cp; ClockRangesPtr storeClockRanges; - struct monitor_ranges *mon_range = NULL; double targetRefresh = 0.0; int numTimings = 0; range hsync[MAX_HSYNC]; @@ -1302,166 +1275,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, } /* - * Probe monitor so that we can enforce/warn about its limits. - * If one or more DS_RANGES descriptions are present, use the parameters - * that they provide. Otherwise, deduce limits based on the modes that - * are shown as supported via standard and detailed timings. - * - * XXX The full potential of the DDC/EDID data still isn't being tapped. - */ - if (scrp->monitor->DDC) { - MonPtr monitor = scrp->monitor; - xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC); - int i, j; - float hmin = 1e6, hmax = 0.0, vmin = 1e6, vmax = 0.0; - float h; - struct std_timings *t; - struct detailed_timings *dt; - - numTimings = 0; - for (i = 0; i < DET_TIMINGS; i++) { - switch (DDC->det_mon[i].type) { - case DS_RANGES: - mon_range = &DDC->det_mon[i].section.ranges; - hsync[numTimings].lo = mon_range->min_h; - hsync[numTimings].hi = mon_range->max_h; - vrefresh[numTimings].lo = mon_range->min_v; - vrefresh[numTimings].hi = mon_range->max_v; - numTimings++; - break; - - case DS_STD_TIMINGS: - t = DDC->det_mon[i].section.std_t; - for (j = 0; j < 5; j++) { - if (t[j].hsize > 256) { /* sanity check */ - if (t[j].refresh < vmin) - vmin = t[i].refresh; - if (t[j].refresh > vmax) - vmax = t[i].refresh; - /* - * For typical modes this is a reasonable estimate - * of the horizontal sync rate. - */ - h = t[j].refresh * 1.07 * t[j].vsize / 1000.0; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - } - break; - - case DT: - dt = &DDC->det_mon[i].section.d_timings; - if (dt->clock > 15000000) { /* sanity check */ - float v; - h = (float)dt->clock / (dt->h_active + dt->h_blanking); - v = h / (dt->v_active + dt->v_blanking); - h /= 1000.0; - if (dt->interlaced) - v /= 2.0; - - if (v < vmin) - vmin = v; - if (v > vmax) - vmax = v; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - break; - } - - if (numTimings > MAX_HSYNC) - break; - } - - if (numTimings == 0) { - t = DDC->timings2; - for (i = 0; i < STD_TIMINGS; i++) { - if (t[i].hsize > 256) { /* sanity check */ - if (t[i].refresh < vmin) - vmin = t[i].refresh; - if (t[i].refresh > vmax) - vmax = t[i].refresh; - /* - * For typical modes this is a reasonable estimate - * of the horizontal sync rate. - */ - h = t[i].refresh * 1.07 * t[i].vsize / 1000.0; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - } - - if (hmax > 0.0) { - hsync[numTimings].lo = hmin; - hsync[numTimings].hi = hmax; - vrefresh[numTimings].lo = vmin; - vrefresh[numTimings].hi = vmax; - numTimings++; - } - } - - if (numTimings > 0) { - -#ifdef DEBUG - for (i = 0; i < numTimings; i++) { - ErrorF("DDC - Hsync %.1f-%.1f kHz - Vrefresh %.1f-%.1f Hz\n", - hsync[i].lo, hsync[i].hi, - vrefresh[i].lo, vrefresh[i].hi); - } -#endif - -#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE - if (monitor->nHsync > 0) { - for (i = 0; i < monitor->nHsync; i++) { - Bool good = FALSE; - for (j = 0; j < numTimings; j++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * hsync[j].lo <= - monitor->hsync[i].lo && - (1.0 + DDC_SYNC_TOLERANCE) * hsync[j].hi >= - monitor->hsync[i].hi) { - good = TRUE; - break; - } - } - if (!good) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "config file hsync range %g-%gkHz not within DDC " - "hsync ranges.\n", - monitor->hsync[i].lo, monitor->hsync[i].hi); - } - } - } - - if (monitor->nVrefresh > 0) { - for (i = 0; i < monitor->nVrefresh; i++) { - Bool good = FALSE; - for (j = 0; j < numTimings; j++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * vrefresh[j].lo <= - monitor->vrefresh[0].lo && - (1.0 + DDC_SYNC_TOLERANCE) * vrefresh[j].hi >= - monitor->vrefresh[0].hi) { - good = TRUE; - break; - } - } - if (!good) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "config file vrefresh range %g-%gHz not within DDC " - "vrefresh ranges.\n", - monitor->vrefresh[i].lo, monitor->vrefresh[i].hi); - } - } - } - } - } - - /* * If requested by the driver, allow missing hsync and/or vrefresh ranges * in the monitor section. */ diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c index 22deca687..ed7fb167a 100644 --- a/hw/xfree86/ddc/ddcProperty.c +++ b/hw/xfree86/ddc/ddcProperty.c @@ -1,159 +1,407 @@ -/* ddcProperty.c: Make the DDC monitor information available to clients - * as properties on the root window - * - * Copyright 1999 by Andrew C Aitchison <A.C.Aitchison@dpmms.cam.ac.uk> +/* + * Copyright 2006 Luc Verhaegen. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif -#include <string.h> -#include "misc.h" #include "xf86.h" -/* #include "xf86_OSproc.h" */ -#include <X11/Xatom.h> -#include "property.h" -#include "propertyst.h" #include "xf86DDC.h" -#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" -#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" -#define VDIF_ATOM_NAME "XFree86_DDC_VDIF_RAWDATA" - -Bool -xf86SetDDCproperties(ScrnInfoPtr pScrnInfo, xf86MonPtr DDC) +/* + * xf86Mode.c should have a some more DisplayModePtr list handling. + */ +static DisplayModePtr +xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) { - Atom EDID1Atom=-1, EDID2Atom=-1, VDIFAtom=-1; - CARD8 *EDID1rawdata = NULL; - CARD8 *EDID2rawdata = NULL; - int i, ret; - Bool makeEDID1prop = FALSE; - Bool makeEDID2prop = FALSE; - -#ifdef DEBUG - ErrorF("xf86SetDDCproperties(%p, %p)\n", pScrnInfo, DDC); -#endif + if (!Modes) { + if (Additions) + return Additions; + else + return NULL; + } - if (pScrnInfo==NULL || pScrnInfo->monitor==NULL || DDC==NULL) { - return FALSE; + if (Additions) { + DisplayModePtr Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + Mode->next = Additions; + Additions->prev = Mode; } -#ifdef DEBUG - ErrorF("pScrnInfo->scrnIndex %d\n", pScrnInfo->scrnIndex); + return Modes; +} + +static DisplayModePtr +xf86ModeCopy(DisplayModePtr Mode) +{ + DisplayModePtr New; + + if (!Mode) + return NULL; + + New = xnfalloc(sizeof(DisplayModeRec)); + + memcpy(New, Mode, sizeof(DisplayModeRec)); + + New->name = xnfalloc(strlen(Mode->name) + 1); + memcpy(New->name, Mode->name, strlen(Mode->name) + 1); + + /* We ignore privates as DDC code doesn't use it currently */ + return New; +} + +/* + * Temporary. + */ +static void +add(char **p, char *new) +{ + *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); + strcat(*p, " "); + strcat(*p, new); +} - ErrorF("pScrnInfo->monitor was %p\n", pScrnInfo->monitor); +static void +PrintModeline(int scrnIndex,DisplayModePtr mode) +{ + char tmp[256]; + char *flags = xnfcalloc(1, 1); + + if (mode->HSkew) { + snprintf(tmp, 256, "hskew %i", mode->HSkew); + add(&flags, tmp); + } + if (mode->VScan) { + snprintf(tmp, 256, "vscan %i", mode->VScan); + add(&flags, tmp); + } + if (mode->Flags & V_INTERLACE) add(&flags, "interlace"); + if (mode->Flags & V_CSYNC) add(&flags, "composite"); + if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan"); + if (mode->Flags & V_BCAST) add(&flags, "bcast"); + if (mode->Flags & V_PHSYNC) add(&flags, "+hsync"); + if (mode->Flags & V_NHSYNC) add(&flags, "-hsync"); + if (mode->Flags & V_PVSYNC) add(&flags, "+vsync"); + if (mode->Flags & V_NVSYNC) add(&flags, "-vsync"); + if (mode->Flags & V_PCSYNC) add(&flags, "+csync"); + if (mode->Flags & V_NCSYNC) add(&flags, "-csync"); +#if 0 + if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); #endif + xf86DrvMsgVerb(scrnIndex, X_INFO, 3, + "Modeline \"%s\" %6.2f %i %i %i %i %i %i %i %i%s\n", + mode->name, mode->Clock/1000., mode->HDisplay, + mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, + mode->VTotal, flags); + xfree(flags); +} + +/* + * TODO: + * - for those with access to the VESA DMT standard; review please. + * - swap M_T_DEFAULT for M_T_EDID_... + */ +#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DEFAULT +#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 + +DisplayModeRec DDCEstablishedModes[17] = { + { MODEPREFIX("800x600"), 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ + { MODEPREFIX("800x600"), 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ + { MODEPREFIX("640x480"), 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ + { MODEPREFIX("640x480"), 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX("640x480"), 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */ + { MODEPREFIX("640x480"), 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX("720x400"), 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */ + { MODEPREFIX("720x400"), 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */ + { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ + { MODEPREFIX("1024x768"), 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX("1024x768"), 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ + { MODEPREFIX("1024x768"), 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ + { MODEPREFIX("1024x768"), 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ + { MODEPREFIX("832x624"), 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */ + { MODEPREFIX("800x600"), 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ + { MODEPREFIX("800x600"), 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ + { MODEPREFIX("1152x864"), 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ +}; + +static DisplayModePtr +DDCModesFromEstablished(int scrnIndex, struct established_timings *timing) +{ + DisplayModePtr Modes = NULL, Mode = NULL; + CARD32 bits = (timing->t1) | (timing->t2 << 8) | + ((timing->t_manu & 0x80) << 9); + int i; + + for (i = 0; i < 17; i++) + if (bits & (0x01 << i)) { + Mode = xf86ModeCopy(&(DDCEstablishedModes[i])); + Modes = xf86ModesAdd(Modes, Mode); + } + + return Modes; +} + +/* + * + */ +static DisplayModePtr +DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing) +{ + DisplayModePtr Modes = NULL, Mode = NULL; + int i; + + for (i = 0; i < 5; i++) + if (timing[i].hsize && timing[i].vsize && timing[i].refresh) { + Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize, + timing[i].refresh, FALSE, FALSE); + Modes = xf86ModesAdd(Modes, Mode); + } + + return Modes; +} - pScrnInfo->monitor->DDC = DDC; - - if (DDC->ver.version == 1) { - makeEDID1prop = TRUE; - } else if (DDC->ver.version == 2) { - int checksum1; - int checksum2; - makeEDID2prop = TRUE; - - /* Some monitors (eg Panasonic PanaSync4) - * report version==2 because they used EDID v2 spec document, - * although they use EDID v1 data structure :-( - * - * Try using checksum to determine when we have such a monitor. - */ - checksum2 = 0; - for (i=0; i<256; i++) { checksum2 += DDC->rawData[i]; } - if ( (checksum2 % 256) != 0 ) { - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v2 checksum failed\n"); - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); - checksum1 = 0; - for (i=0; i<128; i++) { checksum1 += DDC->rawData[i]; } - if ( (checksum1 % 256) == 0 ) { - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v1 checksum passed,\n"); - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID1_RAWDATA property created\n"); - makeEDID1prop = TRUE; - } - } - } else { - xf86DrvMsg(pScrnInfo->scrnIndex, X_PROBED, - "unexpected EDID version %d revision %d\n", - DDC->ver.version, DDC->ver.revision ); +/* + * + */ +static DisplayModePtr +DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing) +{ + DisplayModePtr Mode; + + /* We don't do stereo */ + if (timing->stereo) { + xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We don't handle stereo.\n", + __func__); + return NULL; + } + + /* We only do seperate sync currently */ + if (timing->sync != 0x03) { + xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We only handle seperate" + " sync.\n", __func__); + return NULL; } + + Mode = xnfalloc(sizeof(DisplayModeRec)); + memset(Mode, 0, sizeof(DisplayModeRec)); + + Mode->name = xnfalloc(10); /* "1234x1234" */ + xf86snprintf(Mode->name, 20, "%dx%d", timing->h_active, + timing->v_active); + + Mode->type = M_T_DEFAULT; /* get ourselves a nice type of our own */ + + Mode->Clock = timing->clock / 1000.0; + + Mode->HDisplay = timing->h_active; + Mode->HSyncStart = timing->h_active + timing->h_sync_off; + Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width; + Mode->HTotal = timing->h_active + timing->h_blanking; + + Mode->VDisplay = timing->v_active; + Mode->VSyncStart = timing->v_active + timing->v_sync_off; + Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width; + Mode->VTotal = timing->v_active + timing->v_blanking; + + /* We ignore h/v_size and h/v_border for now. */ + + if (timing->interlaced) + Mode->Flags |= V_INTERLACE; + + if (timing->misc & 0x02) + Mode->Flags |= V_PHSYNC; + else + Mode->Flags |= V_NHSYNC; + + if (timing->misc & 0x01) + Mode->Flags |= V_PVSYNC; + else + Mode->Flags |= V_NVSYNC; + + return Mode; +} - if (makeEDID1prop) { - if ( (EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL ) { - return FALSE; - } +/* + * + */ +static void +DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) +{ + DisplayModePtr Mode = Modes; - EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME), TRUE); + if (!Monitor || !Modes) + return; + /* set up the ranges for scanning through the modes */ + Monitor->nHsync = 1; + Monitor->hsync[0].lo = 1024.0; + Monitor->hsync[0].hi = 0.0; - for (i=0; i<128; i++) { - EDID1rawdata[i] = DDC->rawData[i]; - } + Monitor->nVrefresh = 1; + Monitor->vrefresh[0].lo = 1024.0; + Monitor->vrefresh[0].hi = 0.0; -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata ); -#endif + while (Mode) { + if (!Mode->HSync) + Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); - } - - if (makeEDID2prop) { - if ( (EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL ) { - return FALSE; - } - for (i=0; i<256; i++) { - EDID2rawdata[i] = DDC->rawData[i]; - } - - EDID2Atom = MakeAtom(EDID2_ATOM_NAME, sizeof(EDID2_ATOM_NAME), TRUE); - -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - EDID2Atom, XA_INTEGER, 8, - 256, (unsigned char *)EDID2rawdata ); -#endif - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - EDID2Atom, XA_INTEGER, 8, - 256, (unsigned char *)EDID2rawdata - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + if (!Mode->VRefresh) + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); + + if (Mode->HSync < Monitor->hsync[0].lo) + Monitor->hsync[0].lo = Mode->HSync; + + if (Mode->HSync > Monitor->hsync[0].hi) + Monitor->hsync[0].hi = Mode->HSync; + + if (Mode->VRefresh < Monitor->vrefresh[0].lo) + Monitor->vrefresh[0].lo = Mode->VRefresh; + + if (Mode->VRefresh > Monitor->vrefresh[0].hi) + Monitor->vrefresh[0].hi = Mode->VRefresh; + + Mode = Mode->next; } +} - if (DDC->vdif) { -#define VDIF_DUMMY_STRING "setting dummy VDIF property - please insert correct values\n" -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - VDIFAtom, XA_STRING, 8, - strlen(VDIF_DUMMY_STRING), VDIF_DUMMY_STRING - ); -#endif +/* + * Fill out MonPtr with xf86MonPtr information. + */ +void +xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) +{ + DisplayModePtr Modes = NULL, Mode; + int i; + + if (!Monitor || !DDC) + return; + Monitor->DDC = DDC; - VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE); + if (DDC->features.gamma > 0.0) { + Monitor->gamma.red = DDC->features.gamma; + Monitor->gamma.green = DDC->features.gamma; + Monitor->gamma.blue = DDC->features.gamma; + } + + Monitor->widthmm = 10 * DDC->features.hsize; + Monitor->heightmm = 10 * DDC->features.vsize; + + /* If this is a digital display, then we can use reduced blanking */ + if (DDC->features.input_type) + Monitor->reducedblanking = TRUE; + /* Allow the user to also enable this through config */ + + /* Add established timings */ + Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1); + Modes = xf86ModesAdd(Modes, Mode); + + /* Add standard timings */ + Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2); + Modes = xf86ModesAdd(Modes, Mode); + + /* Go through the detailed monitor sections */ + for (i = 0; i < DET_TIMINGS; i++) + switch (DDC->det_mon[i].type) { + case DS_RANGES: + if (Monitor->nHsync && Monitor->nVrefresh) { + xf86DrvMsg(scrnIndex, X_INFO, "Ignoring EDID Ranges. Using" + " configured ranges.\n"); + break; + } + + xf86DrvMsg(scrnIndex, X_INFO, "Using EDID ranges info for Monitor" + " timing.\n"); + Monitor->nHsync = 1; + Monitor->hsync[0].lo = DDC->det_mon[i].section.ranges.min_h; + Monitor->hsync[0].hi = DDC->det_mon[i].section.ranges.max_h; + + Monitor->nVrefresh = 1; + Monitor->vrefresh[0].lo = DDC->det_mon[i].section.ranges.min_v; + Monitor->vrefresh[0].hi = DDC->det_mon[i].section.ranges.max_v; + + break; + case DT: + Mode = DDCModeFromDetailedTiming(scrnIndex, + &DDC->det_mon[i].section.d_timings); + Modes = xf86ModesAdd(Modes, Mode); + break; + case DS_STD_TIMINGS: + Mode = DDCModesFromStandardTiming(scrnIndex, + DDC->det_mon[i].section.std_t); + Modes = xf86ModesAdd(Modes, Mode); + break; + default: + break; + } + + if (Modes) { + /* Print Modes */ + xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n"); + + Mode = Modes; + while (Mode) { + PrintModeline(scrnIndex, Mode); + Mode = Mode->next; + } - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - VDIFAtom, XA_STRING, 8, - strlen(VDIF_DUMMY_STRING), - VDIF_DUMMY_STRING - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + /* Do we still need ranges to be filled in? */ + if (!Monitor->nHsync || !Monitor->nVrefresh) + DDCGuessRangesFromModes(scrnIndex, Monitor, Modes); + + /* look for last Mode */ + Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + /* add to MonPtr */ + if (Monitor->Modes) { + Monitor->Last->next = Modes; + Modes->prev = Monitor->Last; + Monitor->Last = Mode; + } else { + Monitor->Modes = Modes; + Monitor->Last = Mode; + } } +} + +/* + * Empty shell that keeps most drivers happy. + */ +Bool +xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + if (!pScrn || !pScrn->monitor || !DDC) + return FALSE; + + xf86DDCMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); return TRUE; } diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h index fb1083606..5def97a81 100644 --- a/hw/xfree86/ddc/xf86DDC.h +++ b/hw/xfree86/ddc/xf86DDC.h @@ -47,6 +47,9 @@ extern xf86vdifPtr xf86InterpretVdif( CARD8 *c ); +extern void +xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); + extern Bool xf86SetDDCproperties( ScrnInfoPtr pScreen, xf86MonPtr DDC |