? doc/Xserver.1x ? hw/dmx/Xdmx.1x ? hw/dmx/config/dmxtodmx.1x ? hw/dmx/config/vdltodmx.1x ? hw/dmx/config/xdmxconfig.1x Index: hw/xfree86/common/Makefile.am =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/common/Makefile.am,v retrieving revision 1.17 diff -u -r1.17 Makefile.am --- hw/xfree86/common/Makefile.am 2 Dec 2005 06:02:40 -0000 1.17 +++ hw/xfree86/common/Makefile.am 5 Jan 2006 05:48:14 -0000 @@ -31,7 +31,7 @@ AM_LDFLAGS = -r libcommon_a_SOURCES = xf86Configure.c xf86Bus.c xf86Config.c \ - xf86Cursor.c xf86DGA.c xf86DPMS.c \ + xf86Cursor.c xf86cvt.c xf86DGA.c xf86DPMS.c \ xf86DoProbe.c xf86DoScanPci.c xf86Events.c \ xf86Globals.c xf86Io.c xf86AutoConfig.c \ xf86MiscExt.c xf86Option.c \ Index: hw/xfree86/common/xf86.h =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/common/xf86.h,v retrieving revision 1.10 diff -u -r1.10 xf86.h --- hw/xfree86/common/xf86.h 29 Oct 2005 21:31:23 -0000 1.10 +++ hw/xfree86/common/xf86.h 5 Jan 2006 05:48:14 -0000 @@ -416,6 +416,8 @@ void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags); void xf86PrintModes(ScrnInfoPtr scrp); void xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges); +DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); /* xf86Option.c */ Index: hw/xfree86/common/xf86Mode.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/common/xf86Mode.c,v retrieving revision 1.8 diff -u -r1.8 xf86Mode.c --- hw/xfree86/common/xf86Mode.c 28 Dec 2005 15:22:21 -0000 1.8 +++ hw/xfree86/common/xf86Mode.c 5 Jan 2006 05:48:15 -0000 @@ -47,7 +47,6 @@ #include "globals.h" #include "xf86.h" #include "xf86Priv.h" -#include "xf86DDC.h" /* * xf86GetNearestClock -- @@ -752,31 +751,6 @@ 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) @@ -1244,7 +1218,6 @@ PixmapFormatRec *BankFormat; ClockRangePtr cp; ClockRangesPtr storeClockRanges; - struct monitor_ranges *mon_range = NULL; double targetRefresh = 0.0; int numTimings = 0; range hsync[MAX_HSYNC]; @@ -1279,166 +1252,6 @@ } /* - * 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. */ Index: hw/xfree86/common/xf86cvt.c =================================================================== RCS file: hw/xfree86/common/xf86cvt.c diff -N hw/xfree86/common/xf86cvt.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ hw/xfree86/common/xf86cvt.c 5 Jan 2006 05:48:15 -0000 @@ -0,0 +1,292 @@ +/* + * Copyright 2005-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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +/* + * The reason for having this function in a file of its own is + * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode + * code is shared directly. + */ + +#include "xf86.h" + +/* + * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh. + * + * These calculations are stolen from the CVT calculation spreadsheet written + * by Graham Loveridge. He seems to be claiming no copyright and there seems to + * be no license attached to this. He apparently just wants to see his name + * mentioned. + * + * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls + * + * Comments and structure corresponds to the comments and structure of the xls. + * This should ease importing of future changes to the standard (not very + * likely though). + * + * About margins; i'm sure that they are to be the bit between HDisplay and + * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and + * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking + * outside sync "margin" for some reason. Since we prefer seeing proper + * blanking instead of the overscan colour, and since the Crtc* values will + * probably get altered after us, we will disable margins altogether. With + * these calculations, Margins will plainly expand H/VDisplay, and we don't + * want that. -- libv + * + */ +DisplayModePtr +xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, + Bool Interlaced) +{ + DisplayModeRec *Mode = xnfalloc(sizeof(DisplayModeRec)); + + /* 1) top/bottom margin size (% of height) - default: 1.8 */ +#define CVT_MARGIN_PERCENTAGE 1.8 + + /* 2) character cell horizontal granularity (pixels) - default 8 */ +#define CVT_H_GRANULARITY 8 + + /* 4) Minimum vertical porch (lines) - default 3 */ +#define CVT_MIN_V_PORCH 3 + + /* 4) Minimum number of vertical back porch lines - default 6 */ +#define CVT_MIN_V_BPORCH 6 + + /* Pixel Clock step (kHz) */ +#define CVT_CLOCK_STEP 250 + + Bool Margins = FALSE; + float VFieldRate, HPeriod; + int HDisplayRnd, HMargin; + int VDisplayRnd, VMargin, VSync; + float Interlace; /* Please rename this */ + + memset(Mode, 0, sizeof(DisplayModeRec)); + + /* CVT default is 60.0Hz */ + if (!VRefresh) + VRefresh = 60.0; + + /* 1. Required field rate */ + if (Interlaced) + VFieldRate = VRefresh * 2; + else + VFieldRate = VRefresh; + + /* 2. Horizontal pixels */ + HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY); + + /* 3. Determine left and right borders */ + if (Margins) { + /* right margin is actually exactly the same as left */ + HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); + HMargin -= HMargin % CVT_H_GRANULARITY; + } else + HMargin = 0; + + /* 4. Find total active pixels */ + Mode->HDisplay = HDisplayRnd + 2*HMargin; + + /* 5. Find number of lines per field */ + if (Interlaced) + VDisplayRnd = VDisplay / 2; + else + VDisplayRnd = VDisplay; + + /* 6. Find top and bottom margins */ + /* nope. */ + if (Margins) + /* top and bottom margins are equal again. */ + VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); + else + VMargin = 0; + + Mode->VDisplay = VDisplay + 2*VMargin; + + /* 7. Interlace */ + if (Interlaced) + Interlace = 0.5; + else + Interlace = 0.0; + + /* Determine VSync Width from aspect ratio */ + if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) + VSync = 4; + else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) + VSync = 5; + else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) + VSync = 6; + else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) + VSync = 7; + else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)) + VSync = 7; + else /* Custom */ + VSync = 10; + + if (!Reduced) { /* simplified GTF calculation */ + + /* 4) Minimum time of vertical sync + back porch interval (µs) + * default 550.0 */ +#define CVT_MIN_VSYNC_BP 550.0 + + /* 3) Nominal HSync width (% of line period) - default 8 */ +#define CVT_HSYNC_PERCENTAGE 8 + + float HBlankPercentage; + int VSyncAndBackPorch, VBackPorch; + int HBlank; + + /* 8. Estimated Horizontal period */ + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / + (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace); + + /* 9. Find number of lines in sync + backporch */ + if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH)) + VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH; + else + VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1; + + /* 10. Find number of lines in back porch */ + VBackPorch = VSyncAndBackPorch - VSync; + + /* 11. Find total number of lines in vertical field */ + Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace + + CVT_MIN_V_PORCH; + + /* 5) Definition of Horizontal blanking time limitation */ + /* Gradient (%/kHz) - default 600 */ +#define CVT_M_FACTOR 600 + + /* Offset (%) - default 40 */ +#define CVT_C_FACTOR 40 + + /* Blanking time scaling factor - default 128 */ +#define CVT_K_FACTOR 128 + + /* Scaling factor weighting - default 20 */ +#define CVT_J_FACTOR 20 + +#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 +#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ + CVT_J_FACTOR + + /* 12. Find ideal blanking duty cycle from formula */ + HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0; + + /* 13. Blanking time */ + if (HBlankPercentage < 20) + HBlankPercentage = 20; + + HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage); + HBlank -= HBlank % (2*CVT_H_GRANULARITY); + + /* 14. Find total number of pixels in a line. */ + Mode->HTotal = Mode->HDisplay + HBlank; + + /* Fill in HSync values */ + Mode->HSyncEnd = Mode->HDisplay + HBlank / 2; + + Mode->HSyncStart = Mode->HSyncEnd - + (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100; + Mode->HSyncStart += CVT_H_GRANULARITY - + Mode->HSyncStart % CVT_H_GRANULARITY; + + /* Fill in VSync values */ + Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH; + Mode->VSyncEnd = Mode->VSyncStart + VSync; + + } else { /* Reduced blanking */ + /* Minimum vertical blanking interval time (µs) - default 460 */ +#define CVT_RB_MIN_VBLANK 460.0 + + /* Fixed number of clocks for horizontal sync */ +#define CVT_RB_H_SYNC 32.0 + + /* Fixed number of clocks for horizontal blanking */ +#define CVT_RB_H_BLANK 160.0 + + /* Fixed number of lines for vertical front porch - default 3 */ +#define CVT_RB_VFPORCH 3 + + int VBILines; + + /* 8. Estimate Horizontal period. */ + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / + (VDisplayRnd + 2*VMargin); + + /* 9. Find number of lines in vertical blanking */ + VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1; + + /* 10. Check if vertical blanking is sufficient */ + if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)) + VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH; + + /* 11. Find total number of lines in vertical field */ + Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines; + + /* 12. Find total number of pixels in a line */ + Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK; + + /* Fill in HSync values */ + Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2; + Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC; + + /* Fill in VSync values */ + Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH; + Mode->VSyncEnd = Mode->VSyncStart + VSync; + } + + /* 15/13. Find pixel clock frequency (kHz for xf86) */ + Mode->Clock = Mode->HTotal * 1000.0 / HPeriod; + Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP; + + /* 16/14. Find actual Horizontal Frequency (kHz) */ + Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal); + + /* 17/15. Find actual Field rate */ + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); + + /* 18/16. Find actual vertical frame frequency */ + /* ignore - just set the mode flag for interlaced */ + if (Interlaced) + Mode->VTotal *= 2; + + { + char Name[256]; + Name[0] = 0; + + snprintf(Name, 256, "%dx%d", HDisplay, VDisplay); + + Mode->name = xnfalloc(strlen(Name) + 1); + memcpy(Mode->name, Name, strlen(Name) + 1); + } + + if (Reduced) + Mode->Flags |= V_PHSYNC | V_NVSYNC; + else + Mode->Flags |= V_NHSYNC | V_PVSYNC; + + if (Interlaced) + Mode->Flags |= V_INTERLACE; + + return Mode; +} Index: hw/xfree86/ddc/ddcProperty.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/ddc/ddcProperty.c,v retrieving revision 1.6 diff -u -r1.6 ddcProperty.c --- hw/xfree86/ddc/ddcProperty.c 3 Jul 2005 08:53:43 -0000 1.6 +++ hw/xfree86/ddc/ddcProperty.c 5 Jan 2006 05:48:15 -0000 @@ -1,160 +1,407 @@ -/* ddcProperty.c: Make the DDC monitor information available to clients - * as properties on the root window - * - * Copyright 1999 by Andrew C Aitchison +/* + * 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. */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/ddcProperty.c,v 1.9tsi Exp $ */ #ifdef HAVE_XORG_CONFIG_H #include #endif -#include "misc.h" #include "xf86.h" -/* #include "xf86_ansic.h" */ -/* #include "xf86_OSproc.h" */ -#include -#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" +/* + * xf86Mode.c should have a some more DisplayModePtr list handling. + */ +static DisplayModePtr +xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) +{ + if (!Modes) { + if (Additions) + return Additions; + else + return NULL; + } -Bool -xf86SetDDCproperties(ScrnInfoPtr pScrnInfo, xf86MonPtr DDC) + if (Additions) { + DisplayModePtr Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + Mode->next = Additions; + Additions->prev = Mode; + } + + return Modes; +} + +static DisplayModePtr +xf86ModeCopy(DisplayModePtr Mode) { - Atom EDID1Atom=-1, EDID2Atom=-1, VDIFAtom=-1; - CARD8 *EDID1rawdata = NULL; - CARD8 *EDID2rawdata = NULL; - int i, ret; - Bool makeEDID1prop = FALSE; - Bool makeEDID2prop = FALSE; + 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); -#ifdef DEBUG - ErrorF("xf86SetDDCproperties(%p, %p)\n", pScrnInfo, DDC); + /* 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); +} + +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); +} - if (pScrnInfo==NULL || pScrnInfo->monitor==NULL || DDC==NULL) { - return FALSE; +/* + * 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; +} + +/* + * + */ +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; +} -#ifdef DEBUG - ErrorF("pScrnInfo->scrnIndex %d\n", pScrnInfo->scrnIndex); +/* + * + */ +static void +DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) +{ + DisplayModePtr Mode = Modes; - ErrorF("pScrnInfo->monitor was %p\n", pScrnInfo->monitor); -#endif + if (!Monitor || !Modes) + return; - pScrnInfo->monitor->DDC = DDC; + /* set up the ranges for scanning through the modes */ + Monitor->nHsync = 1; + Monitor->hsync[0].lo = 1024.0; + Monitor->hsync[0].hi = 0.0; - 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 ); - } - - if (makeEDID1prop) { - if ( (EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL ) { - return FALSE; - } - - EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME), TRUE); - - - for (i=0; i<128; i++) { - EDID1rawdata[i] = DDC->rawData[i]; - } - -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata ); -#endif + Monitor->nVrefresh = 1; + Monitor->vrefresh[0].lo = 1024.0; + Monitor->vrefresh[0].hi = 0.0; - 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 (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 + while (Mode) { + if (!Mode->HSync) + Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); + if (!Mode->VRefresh) + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); - VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE); + if (Mode->HSync < Monitor->hsync[0].lo) + Monitor->hsync[0].lo = Mode->HSync; - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - VDIFAtom, XA_STRING, 8, - strlen(VDIF_DUMMY_STRING), - VDIF_DUMMY_STRING - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + 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; + } +} + +/* + * 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; + + 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; + } + + /* 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; } Index: hw/xfree86/ddc/edid.h =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/ddc/edid.h,v retrieving revision 1.6 diff -u -r1.6 edid.h --- hw/xfree86/ddc/edid.h 24 Aug 2005 11:18:33 -0000 1.6 +++ hw/xfree86/ddc/edid.h 5 Jan 2006 05:48:15 -0000 @@ -227,9 +227,9 @@ #define STEREO _STEREO(c) #define _STEREO1(x) (x[17] & 0x1) #define STEREO1 _STEREO(c) -#define _SYNC_T(x) ((x[17] & 0x18) >> 4) +#define _SYNC_T(x) ((x[17] & 0x18) >> 3) #define SYNC_T _SYNC_T(c) -#define _MISC(x) ((x[17] & 0x06) >> 2) +#define _MISC(x) ((x[17] & 0x06) >> 1) #define MISC _MISC(c) #define _MONITOR_DESC_TYPE(x) x[3] @@ -411,6 +411,7 @@ #define DS_WHITE_P 0xFB #define DS_STD_TIMINGS 0xFA #define DS_DUMMY 0x10 +#define DS_UNKOWN 0x100 /* type is an int */ struct monitor_ranges { int min_v; Index: hw/xfree86/ddc/interpret_edid.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/ddc/interpret_edid.c,v retrieving revision 1.7 diff -u -r1.7 interpret_edid.c --- hw/xfree86/ddc/interpret_edid.c 3 Jul 2005 08:53:43 -0000 1.7 +++ hw/xfree86/ddc/interpret_edid.c 5 Jan 2006 05:48:15 -0000 @@ -174,6 +174,9 @@ case ADD_DUMMY: det_mon[i].type = DS_DUMMY; break; + default: + det_mon[i].type = DS_UNKOWN; + break; } } else { det_mon[i].type = DT; Index: hw/xfree86/ddc/xf86DDC.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/ddc/xf86DDC.c,v retrieving revision 1.7 diff -u -r1.7 xf86DDC.c --- hw/xfree86/ddc/xf86DDC.c 18 Nov 2005 18:02:24 -0000 1.7 +++ hw/xfree86/ddc/xf86DDC.c 5 Jan 2006 05:48:15 -0000 @@ -119,16 +119,35 @@ int len ); +static void +EDIDDump(int scrnIndex, xf86MonPtr DDC); + +/* Pure for testing/debugging. No user should ever do this. */ +#define HAVEEDIDLOAD 1 + +#ifdef HAVEEDIDLOAD +static unsigned char * EDIDLoad(int scrnIndex, char *FileName); +#endif + typedef enum { DDCOPT_NODDC1, DDCOPT_NODDC2, - DDCOPT_NODDC + DDCOPT_NODDC, +#ifdef HAVEEDIDLOAD + DDCOPT_LOAD, +#endif + DDCOPT_DUMP } DDCOpts; static const OptionInfoRec DDCOptions[] = { { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, +#ifdef HAVEEDIDLOAD + { DDCOPT_LOAD, "LoadDDC", OPTV_ANYSTR, {0}, FALSE }, +#endif + { DDCOPT_DUMP, "DumpDDC", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE }, }; @@ -152,8 +171,11 @@ xf86MonPtr tmp = NULL; int sigio; /* Default DDC and DDC1 to enabled. */ - Bool noddc = FALSE, noddc1 = FALSE; + Bool noddc = FALSE, noddc1 = FALSE, dump; OptionInfoPtr options; +#ifdef HAVEEDIDLOAD + char *LoadName = NULL; +#endif options = xnfalloc(sizeof(DDCOptions)); (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); @@ -161,15 +183,28 @@ xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); + dump = xf86ReturnOptValBool(options, DDCOPT_DUMP, FALSE); + +#ifdef HAVEEDIDLOAD + LoadName = xf86GetOptValString(options, DDCOPT_LOAD); +#endif + xfree(options); if (noddc || noddc1) return NULL; - - sigio = xf86BlockSIGIO(); - EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); - xf86UnblockSIGIO(sigio); +#ifdef HAVEEDIDLOAD + if (LoadName) + EDID_block = EDIDLoad(scrnIndex, LoadName); +#endif + + if (!EDID_block) { + sigio = xf86BlockSIGIO(); + EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); + xf86UnblockSIGIO(sigio); + } + if (EDID_block){ tmp = xf86InterpretEDID(scrnIndex,EDID_block); } @@ -178,7 +213,11 @@ if (!tmp) ErrorF("Cannot interpret EDID block\n"); #endif - return tmp; + + if (tmp && dump) + EDIDDump(scrnIndex, tmp); + + return tmp; } xf86MonPtr @@ -189,8 +228,11 @@ unsigned char *VDIF_Block = NULL; xf86MonPtr tmp = NULL; /* Default DDC and DDC2 to enabled. */ - Bool noddc = FALSE, noddc2 = FALSE; + Bool noddc = FALSE, noddc2 = FALSE, dump; OptionInfoPtr options; +#ifdef HAVEEDIDLOAD + char *LoadName = NULL; +#endif options = xnfalloc(sizeof(DDCOptions)); (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); @@ -198,12 +240,24 @@ xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); + dump = xf86ReturnOptValBool(options, DDCOPT_DUMP, FALSE); + +#ifdef HAVEEDIDLOAD + LoadName = xf86GetOptValString(options, DDCOPT_LOAD); +#endif + xfree(options); if (noddc || noddc2) return NULL; - EDID_block = EDID1Read_DDC2(scrnIndex,pBus); +#ifdef HAVEEDIDLOAD + if (LoadName) + EDID_block = EDIDLoad(scrnIndex, LoadName); +#endif + + if (!EDID_block) + EDID_block = EDID1Read_DDC2(scrnIndex,pBus); if (EDID_block){ tmp = xf86InterpretEDID(scrnIndex,EDID_block); @@ -224,7 +278,10 @@ VDIFRead(scrnIndex, pBus, EDID1_LEN * (tmp->no_sections + 1)); tmp->vdif = xf86InterpretVdif(VDIF_Block); } - + + if (tmp && dump) + EDIDDump(scrnIndex, tmp); + return tmp; } @@ -385,3 +442,58 @@ xfree(R_Buffer); return NULL; } + +/* + * Provide a means to dump edid blocks for debugging use. + */ +static void +EDIDDump(int scrnIndex, xf86MonPtr DDC) +{ + XF86FILE *EdidFile = NULL; + char FileName[20]; + + xf86snprintf(FileName, 20, "/tmp/%s-%04X.edid", DDC->vendor.name, + DDC->vendor.prod_id); + + xf86DrvMsg(scrnIndex, X_INFO, "Dumping EDID block to %s\n", FileName); + + EdidFile = xf86fopen(FileName, "w"); + if (!EdidFile) { + xf86DrvMsg(scrnIndex, X_WARNING, "Failed to open %s\n", FileName); + return; + } + + xf86fwrite(DDC->rawData, EDID1_LEN, 1, EdidFile); + xf86fclose(EdidFile); +} + +#ifdef HAVEEDIDLOAD +/* + * This one allows devs to easily test different edid blocks. + */ +static unsigned char * +EDIDLoad(int scrnIndex, char *FileName) +{ + XF86FILE *EdidFile = NULL; + unsigned char *Edid = NULL; + + xf86DrvMsg(scrnIndex, X_WARNING, "Loading %s for DDC information.\n", FileName); + xf86DrvMsg(scrnIndex, X_WARNING, "This should only be used for testing!\n"); + + EdidFile = xf86fopen(FileName, "r"); + if (!EdidFile) { + xf86DrvMsg(scrnIndex, X_WARNING, "Failed to open %s\n", FileName); + return NULL; + } + + Edid = xnfalloc(EDID1_LEN); + + if (EDID1_LEN != xf86fread(Edid, 1, EDID1_LEN, EdidFile)) { + xf86DrvMsg(scrnIndex, X_WARNING, "Failed to read from %s\n", FileName); + xfree(Edid); + return NULL; + } + + return Edid; +} +#endif Index: hw/xfree86/ddc/xf86DDC.h =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/ddc/xf86DDC.h,v retrieving revision 1.6 diff -u -r1.6 xf86DDC.h --- hw/xfree86/ddc/xf86DDC.h 24 Aug 2005 11:18:33 -0000 1.6 +++ hw/xfree86/ddc/xf86DDC.h 5 Jan 2006 05:48:15 -0000 @@ -48,6 +48,9 @@ CARD8 *c ); +extern void +xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); + extern Bool xf86SetDDCproperties( ScrnInfoPtr pScreen, xf86MonPtr DDC Index: hw/xfree86/loader/xf86sym.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/loader/xf86sym.c,v retrieving revision 1.18 diff -u -r1.18 xf86sym.c --- hw/xfree86/loader/xf86sym.c 30 Oct 2005 09:27:06 -0000 1.18 +++ hw/xfree86/loader/xf86sym.c 5 Jan 2006 05:48:15 -0000 @@ -542,6 +542,9 @@ SYMFUNC(xf86PrintModes) SYMFUNC(xf86ShowClockRanges) + /* xf86cvt.c */ + SYMFUNC(xf86CVTMode) + /* xf86Option.c */ SYMFUNC(xf86CollectOptions) SYMFUNC(xf86CollectInputOptions) Index: hw/xfree86/utils/cvt/.cvsignore =================================================================== RCS file: hw/xfree86/utils/cvt/.cvsignore diff -N hw/xfree86/utils/cvt/.cvsignore --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ hw/xfree86/utils/cvt/.cvsignore 5 Jan 2006 05:48:15 -0000 @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.deps +.libs +cvt +cvt.man Index: hw/xfree86/utils/cvt/Makefile.am =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/utils/cvt/Makefile.am,v retrieving revision 1.1 diff -u -r1.1 Makefile.am --- hw/xfree86/utils/cvt/Makefile.am 28 Dec 2005 15:22:21 -0000 1.1 +++ hw/xfree86/utils/cvt/Makefile.am 5 Jan 2006 05:48:15 -0000 @@ -33,7 +33,7 @@ cvt_SOURCES = cvt.c cvt_CFLAGS = $(XORG_CFLAGS) -cvt_LDADD = ../../dummylib/libdummy-nonserver.a +cvt_LDADD = ../../dummylib/libdummy-nonserver.a ../../common/xf86cvt.o man1_MANS = cvt.man Index: hw/xfree86/utils/cvt/cvt.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/hw/xfree86/utils/cvt/cvt.c,v retrieving revision 1.1 diff -u -r1.1 cvt.c --- hw/xfree86/utils/cvt/cvt.c 28 Dec 2005 15:22:21 -0000 1.1 +++ hw/xfree86/utils/cvt/cvt.c 5 Jan 2006 05:48:15 -0000 @@ -1,6 +1,5 @@ /* - * Copyright (c) 2005 by Luc Verhaegen. - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * Copyright 2005-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"), @@ -20,344 +19,18 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). */ -/* - * Calculate VESA CVT standard timing modelines. - * - * My own copyright is added. This is only there for the standalone version. - * I don't want to polute the xf86Mode.c license. - * - */ -#include "xf86.h" - - -/* - * Grabbed from xf86Mode.c from the Xorg tree. Hence the copyright and license. - * - * Altered for stdout printing. - */ -static void -add(char **p, char *new) -{ - *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); - strcat(*p, " "); - strcat(*p, new); -} - -static void -PrintModeline(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 - - printf("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); -} - - -/* - * New code... Well, somewhat. - */ - - -/* - * These calculations are stolen from the CVT calculation spreadsheet written - * by Graham Loveridge. He seems to be claiming no copyright and there seems to - * be no license attached to this. He apparently just wants to see his name - * mentioned. - * - * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls - * - * Comments and structure corresponds to the comments and structure of the xls. - * This should ease importing of future changes to the standard (not very - * likely though). - * - * About margins; i'm sure that they are to be the bit between HDisplay and - * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and - * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking - * outside sync "margin" for some reason. Since we prefer seeing proper - * blanking instead of the overscan colour, and since the Crtc* values will - * probably get altered after us, we will disable margins altogether. With - * these calculations, Margins will plainly expand H/VDisplay, and we don't - * want that. - * - */ -static DisplayModeRec * -xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, - Bool Interlaced) -{ - DisplayModeRec *Mode = xnfalloc(sizeof(DisplayModeRec)); - - /* 1) top/bottom margin size (% of height) - default: 1.8 */ -#define CVT_MARGIN_PERCENTAGE 1.8 - - /* 2) character cell horizontal granularity (pixels) - default 8 */ -#define CVT_H_GRANULARITY 8 - - /* 4) Minimum vertical porch (lines) - default 3 */ -#define CVT_MIN_V_PORCH 3 - - /* 4) Minimum number of vertical back porch lines - default 6 */ -#define CVT_MIN_V_BPORCH 6 - - /* Pixel Clock step (kHz) */ -#define CVT_CLOCK_STEP 250 - - Bool Margins = FALSE; - float VFieldRate, HPeriod; - int HDisplayRnd, HMargin; - int VDisplayRnd, VMargin, VSync; - float Interlace; /* Please rename this */ - - /* CVT default is 60.0Hz */ - if (!VRefresh) - VRefresh = 60.0; - - /* 1. Required field rate */ - if (Interlaced) - VFieldRate = VRefresh * 2; - else - VFieldRate = VRefresh; - - /* 2. Horizontal pixels */ - HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY); - - /* 3. Determine left and right borders */ - if (Margins) { - /* right margin is actually exactly the same as left */ - HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); - HMargin -= HMargin % CVT_H_GRANULARITY; - } else - HMargin = 0; - - /* 4. Find total active pixels */ - Mode->HDisplay = HDisplayRnd + 2*HMargin; - - /* 5. Find number of lines per field */ - if (Interlaced) - VDisplayRnd = VDisplay / 2; - else - VDisplayRnd = VDisplay; - - /* 6. Find top and bottom margins */ - /* nope. */ - if (Margins) - /* top and bottom margins are equal again. */ - VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); - else - VMargin = 0; - - Mode->VDisplay = VDisplay + 2*VMargin; - - /* 7. Interlace */ - if (Interlaced) - Interlace = 0.5; - else - Interlace = 0.0; - - /* Determine VSync Width from aspect ratio */ - if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) - VSync = 4; - else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) - VSync = 5; - else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) - VSync = 6; - else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) - VSync = 7; - else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)) - VSync = 7; - else /* Custom */ - VSync = 10; - - if (!Reduced) { /* simplified GTF calculation */ - - /* 4) Minimum time of vertical sync + back porch interval (µs) - * default 550.0 */ -#define CVT_MIN_VSYNC_BP 550.0 - - /* 3) Nominal HSync width (% of line period) - default 8 */ -#define CVT_HSYNC_PERCENTAGE 8 - - float HBlankPercentage; - int VSyncAndBackPorch, VBackPorch; - int HBlank; - - /* 8. Estimated Horizontal period */ - HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / - (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace); - - /* 9. Find number of lines in sync + backporch */ - if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH)) - VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH; - else - VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1; - - /* 10. Find number of lines in back porch */ - VBackPorch = VSyncAndBackPorch - VSync; - - /* 11. Find total number of lines in vertical field */ - Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace - + CVT_MIN_V_PORCH; - - /* 5) Definition of Horizontal blanking time limitation */ - /* Gradient (%/kHz) - default 600 */ -#define CVT_M_FACTOR 600 - - /* Offset (%) - default 40 */ -#define CVT_C_FACTOR 40 - - /* Blanking time scaling factor - default 128 */ -#define CVT_K_FACTOR 128 - - /* Scaling factor weighting - default 20 */ -#define CVT_J_FACTOR 20 - -#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 -#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ - CVT_J_FACTOR - - /* 12. Find ideal blanking duty cycle from formula */ - HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0; - - /* 13. Blanking time */ - if (HBlankPercentage < 20) - HBlankPercentage = 20; - - HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage); - HBlank -= HBlank % (2*CVT_H_GRANULARITY); - - /* 14. Find total number of pixels in a line. */ - Mode->HTotal = Mode->HDisplay + HBlank; - - /* Fill in HSync values */ - Mode->HSyncEnd = Mode->HDisplay + HBlank / 2; - - Mode->HSyncStart = Mode->HSyncEnd - - (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100; - Mode->HSyncStart += CVT_H_GRANULARITY - - Mode->HSyncStart % CVT_H_GRANULARITY; - - /* Fill in VSync values */ - Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH; - Mode->VSyncEnd = Mode->VSyncStart + VSync; - - } else { /* Reduced blanking */ - /* Minimum vertical blanking interval time (µs) - default 460 */ -#define CVT_RB_MIN_VBLANK 460.0 - - /* Fixed number of clocks for horizontal sync */ -#define CVT_RB_H_SYNC 32.0 - - /* Fixed number of clocks for horizontal blanking */ -#define CVT_RB_H_BLANK 160.0 - - /* Fixed number of lines for vertical front porch - default 3 */ -#define CVT_RB_VFPORCH 3 - - int VBILines; - - /* 8. Estimate Horizontal period. */ - HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / - (VDisplayRnd + 2*VMargin); - - /* 9. Find number of lines in vertical blanking */ - VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1; - - /* 10. Check if vertical blanking is sufficient */ - if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)) - VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH; - - /* 11. Find total number of lines in vertical field */ - Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines; - - /* 12. Find total number of pixels in a line */ - Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK; - - /* Fill in HSync values */ - Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2; - Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC; - - /* Fill in VSync values */ - Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH; - Mode->VSyncEnd = Mode->VSyncStart + VSync; - } - - /* 15/13. Find pixel clock frequency (kHz for xf86) */ - Mode->Clock = Mode->HTotal * 1000.0 / HPeriod; - Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP; - - /* 16/14. Find actual Horizontal Frequency (kHz) */ - Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal); - - /* 17/15. Find actual Field rate */ - Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / - ((float) (Mode->HTotal * Mode->VTotal)); - - /* 18/16. Find actual vertical frame frequency */ - /* ignore - just set the mode flag for interlaced */ - if (Interlaced) - Mode->VTotal *= 2; - - /* Fill in Mode parameters */ - { - char Name[256]; - Name[0] = 0; - if (Reduced) - snprintf(Name, 256, "%dx%dR", HDisplay, VDisplay); - else - snprintf(Name, 256, "%dx%d_%.2f", HDisplay, VDisplay, VRefresh); - Mode->name = xnfalloc(strlen(Name) + 1); - memcpy(Mode->name, Name, strlen(Name)); - } +/* Standalone VESA CVT standard timing modelines generator. */ - if (Reduced) - Mode->Flags |= V_PHSYNC | V_NVSYNC; - else - Mode->Flags |= V_NHSYNC | V_PVSYNC; - - if (Interlaced) - Mode->Flags |= V_INTERLACE; - - return Mode; -} +#include "xf86.h" /* * Quickly check wether this is a CVT standard mode. */ static Bool -xf86CVTCheckStandard(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, +CVTCheckStandard(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, Bool Verbose) { Bool IsCVT = TRUE; @@ -454,6 +127,40 @@ /* + * Originally grabbed from xf86Mode.c. + * + * Ignoring the actual Mode->name, as the user will want something solid + * to grab hold of. + */ +static void +PrintModeline(DisplayModePtr Mode, int HDisplay, int VDisplay, float VRefresh, + Bool Reduced) +{ + if (Reduced) + printf("Modeline \"%dx%dR\" ", HDisplay, VDisplay); + else + printf("Modeline \"%dx%d_%.2f\" ", HDisplay, VDisplay, VRefresh); + + printf("%6.2f %i %i %i %i %i %i %i %i", Mode->Clock/1000., Mode->HDisplay, + Mode->HSyncStart, Mode->HSyncEnd, Mode->HTotal, Mode->VDisplay, + Mode->VSyncStart, Mode->VSyncEnd, Mode->VTotal); + + if (Mode->Flags & V_INTERLACE) + printf(" interlace"); + if (Mode->Flags & V_PHSYNC) + printf(" +hsync"); + if (Mode->Flags & V_NHSYNC) + printf(" -hsync"); + if (Mode->Flags & V_PVSYNC) + printf(" +vsync"); + if (Mode->Flags & V_NVSYNC) + printf(" -vsync"); + + printf("\n"); +} + + +/* * */ int @@ -521,12 +228,12 @@ return 0; } - IsCVT = xf86CVTCheckStandard(HDisplay, VDisplay, VRefresh, Reduced, Verbose); + IsCVT = CVTCheckStandard(HDisplay, VDisplay, VRefresh, Reduced, Verbose); Mode = xf86CVTMode(HDisplay, VDisplay, VRefresh, Reduced, Interlaced); PrintComment(Mode, IsCVT, Reduced); - PrintModeline(Mode); + PrintModeline(Mode, HDisplay, VDisplay, VRefresh, Reduced); return 0; }