Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007, 2008  Luc Verhaegen <lverhaegen@novell.com>
  3.  * Copyright 2007, 2008  Matthias Hopf <mhopf@novell.com>
  4.  * Copyright 2007, 2008  Egbert Eich   <eich@novell.com>
  5.  * Copyright 2007, 2008  Advanced Micro Devices, Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in
  15.  * all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25. #define _PARSE_EDID_
  26.  
  27. #include "common.h"
  28. #include "rhd.h"
  29.  
  30. #include "edid.h"
  31.  
  32. #include "xf86DDC.h"
  33.  
  34. #include "rhd_connector.h"
  35. #include "rhd_modes.h"
  36. #include "rhd_monitor.h"
  37. #ifdef ATOM_BIOS
  38. # include "rhd_atombios.h"
  39. #endif
  40.  
  41. /* From rhd_edid.c */
  42. void RHDMonitorEDIDSet(struct rhdMonitor *Monitor, xf86MonPtr EDID);
  43.  
  44.  
  45. /*
  46.  *
  47.  */
  48.  
  49. void
  50. RHDMonitorPrint(struct rhdMonitor *Monitor)
  51. {
  52.     int i;
  53.  
  54.     xf86Msg(X_NONE, "    Bandwidth: %dMHz\n", Monitor->Bandwidth / 1000);
  55.     xf86Msg(X_NONE, "    Horizontal timing:\n");
  56.     for (i = 0; i < Monitor->numHSync; i++)
  57.         xf86Msg(X_NONE, "        %3.1f - %3.1fkHz\n",  Monitor->HSync[i].lo,
  58.                 Monitor->HSync[i].hi);
  59.     xf86Msg(X_NONE, "    Vertical timing:\n");
  60.     for (i = 0; i < Monitor->numVRefresh; i++)
  61.         xf86Msg(X_NONE, "        %3.1f - %3.1fHz\n",  Monitor->VRefresh[i].lo,
  62.                 Monitor->VRefresh[i].hi);
  63.     xf86Msg(X_NONE, "    DPI: %dx%d\n", Monitor->xDpi, Monitor->yDpi);
  64.     if (Monitor->ReducedAllowed)
  65.         xf86Msg(X_NONE, "    Allows reduced blanking.\n");
  66.     if (Monitor->UseFixedModes)
  67.         xf86Msg(X_NONE, "    Uses Fixed Modes.\n");
  68.  
  69.     if (!Monitor->Modes)
  70.         xf86Msg(X_NONE, "    No modes are provided.\n");
  71.     else {
  72.       DisplayModePtr Mode;
  73.  
  74.         xf86Msg(X_NONE, "    Attached modes:\n");
  75.         for (Mode = Monitor->Modes; Mode; Mode = Mode->next) {
  76.             xf86Msg(X_NONE, "        ");
  77.         RHDPrintModeline(Mode);
  78.       }
  79.     }
  80. }
  81.  
  82.  
  83. #if 0
  84.  
  85. /*
  86.  *
  87.  */
  88. static struct rhdMonitor *
  89. rhdMonitorFromConfig(int scrnIndex, MonPtr Config)
  90. {
  91.     struct rhdMonitor *Monitor;
  92.     DisplayModePtr Mode;
  93.     int i;
  94.  
  95.     Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
  96.  
  97.     Monitor->Name = xnfstrdup(Config->id);
  98.     Monitor->scrnIndex = scrnIndex;
  99.  
  100.     if (Config->nHsync) {
  101.         Monitor->numHSync = Config->nHsync;
  102.         for (i = 0; i < Config->nHsync; i++) {
  103.             Monitor->HSync[i].lo = Config->hsync[i].lo;
  104.             Monitor->HSync[i].hi = Config->hsync[i].hi;
  105.         }
  106.     } else if (!Monitor->numHSync) {
  107.         Monitor->numHSync = 3;
  108.         Monitor->HSync[0].lo = 31.5;
  109.         Monitor->HSync[0].hi = 31.5;
  110.         Monitor->HSync[1].lo = 35.15;
  111.         Monitor->HSync[1].hi = 35.15;
  112.         Monitor->HSync[2].lo = 35.5;
  113.         Monitor->HSync[2].hi = 35.5;
  114.     }
  115.  
  116.     if (Config->nVrefresh) {
  117.         Monitor->numVRefresh = Config->nVrefresh;
  118.         for (i = 0; i < Config->nVrefresh; i++) {
  119.             Monitor->VRefresh[i].lo = Config->vrefresh[i].lo;
  120.             Monitor->VRefresh[i].hi = Config->vrefresh[i].hi;
  121.         }
  122.     } else if (!Monitor->numVRefresh) {
  123.         Monitor->numVRefresh = 1;
  124.         Monitor->VRefresh[0].lo = 50;
  125.         Monitor->VRefresh[0].hi = 61;
  126.     }
  127.  
  128. #ifdef MONREC_HAS_REDUCED
  129.     if (Config->reducedblanking)
  130.         Monitor->ReducedAllowed = TRUE;
  131. #endif
  132.  
  133. #ifdef MONREC_HAS_BANDWIDTH
  134.     if (Config->maxPixClock)
  135.         Monitor->Bandwidth = Config->maxPixClock;
  136. #endif
  137.  
  138.     for (Mode = Config->Modes; Mode; Mode = Mode->next)
  139.         Monitor->Modes = RHDModesAdd(Monitor->Modes, RHDModeCopy(Mode));
  140.  
  141.     return Monitor;
  142. }
  143. #endif
  144.  
  145. /*
  146.  *
  147.  */
  148. static struct rhdMonitor *
  149. rhdMonitorFromDefault(RHDPtr rhdPtr)
  150. {
  151.     struct rhdMonitor *Monitor;
  152.     DisplayModePtr Mode;
  153.  
  154.     Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
  155.  
  156.     Monitor->Name = strdup("Default (SVGA)");
  157.     Monitor->scrnIndex = rhdPtr->scrnIndex;
  158.  
  159.     /* timing for pathetic 14" svga monitors */
  160.     Monitor->numHSync = 3;
  161.     Monitor->HSync[0].lo = 31.5;
  162.     Monitor->HSync[0].hi = 31.5;
  163.     Monitor->HSync[1].lo = 35.15;
  164.     Monitor->HSync[1].hi = 35.15;
  165.     Monitor->HSync[2].lo = 35.5;
  166.     Monitor->HSync[2].hi = 35.5;
  167.  
  168.     Monitor->numVRefresh = 1;
  169.     Monitor->VRefresh[0].lo = 50;
  170.     Monitor->VRefresh[0].hi = 61;
  171.  
  172.     return Monitor;
  173. }
  174.  
  175. /*
  176.  * This function tries to handle a configured monitor correctly.
  177.  *
  178.  * This either can be forced through the option, or is used when
  179.  * no monitors are autodetected.
  180.  */
  181. void
  182. RHDConfigMonitorSet(RHDPtr rhdPtr, Bool UseConfig)
  183. {
  184.   int i;
  185.  
  186.   for (i = 0; i < RHD_CONNECTORS_MAX; i++)
  187.     if (rhdPtr->Connector[i] && rhdPtr->Connector[i]->Monitor)
  188.             break;
  189.  
  190.   if (i == RHD_CONNECTORS_MAX)
  191.         xf86DrvMsg(scrnIndex, X_INFO, "No monitors autodetected; "
  192.                    "attempting to work around this.\n");
  193.  
  194.   if (i == RHD_CONNECTORS_MAX)
  195.   {
  196.     rhdPtr->ConfigMonitor = rhdMonitorFromDefault(rhdPtr);
  197.  
  198.     DBG(dbgprintf("Created monitor from default: \"%s\":\n",
  199.                rhdPtr->ConfigMonitor->Name));
  200.  
  201.     RHDMonitorPrint(rhdPtr->ConfigMonitor);
  202.   };
  203. }
  204.  
  205. /*
  206.  * Make sure that we keep only a single mode in our list. This mode should
  207.  * hopefully match our panel at native resolution correctly.
  208.  */
  209. static void
  210. rhdPanelEDIDModesFilter(struct rhdMonitor *Monitor)
  211. {
  212.   DisplayModeRec *Best = Monitor->Modes, *Mode, *Temp;
  213.  
  214.   RHDFUNC(Monitor);
  215.  
  216.   if (!Best || !Best->next)
  217.     return; /* don't bother */
  218.  
  219.     /* don't go for preferred, just take the biggest */
  220.     for (Mode = Best->next; Mode; Mode = Mode->next) {
  221.     if (((Best->HDisplay <= Mode->HDisplay) &&
  222.          (Best->VDisplay < Mode->VDisplay)) ||
  223.         ((Best->HDisplay < Mode->HDisplay) &&
  224.          (Best->VDisplay <= Mode->VDisplay)))
  225.       Best = Mode;
  226.   }
  227.  
  228.     xf86DrvMsg(Monitor->scrnIndex, X_INFO, "Monitor \"%s\": Using Mode \"%s\""
  229.                " for native resolution.\n", Monitor->Name, Best->name);
  230.  
  231.     /* kill all other modes */
  232.   Mode = Monitor->Modes;
  233.     while (Mode) {
  234.     Temp = Mode->next;
  235.  
  236.         if (Mode != Best) {
  237.             RHDDebug(Monitor->scrnIndex, "Monitor \"%s\": Discarding Mode \"%s\"\n",
  238.                      Monitor->Name, Mode->name);
  239.  
  240.             xfree(Mode->name);
  241.             xfree(Mode);
  242.     }
  243.     Mode = Temp;
  244.   }
  245.  
  246.   Best->next = NULL;
  247.   Best->prev = NULL;
  248.   Best->type |= M_T_PREFERRED;
  249.     Monitor->NativeMode = Best;
  250.     Monitor->Modes = Monitor->NativeMode;
  251.   Monitor->numHSync = 1;
  252.   Monitor->HSync[0].lo = Best->HSync;
  253.   Monitor->HSync[0].hi = Best->HSync;
  254.   Monitor->numVRefresh = 1;
  255.   Monitor->VRefresh[0].lo = Best->VRefresh;
  256.   Monitor->VRefresh[0].hi = Best->VRefresh;
  257.   Monitor->Bandwidth = Best->Clock;
  258. }
  259.  
  260. /*
  261.  *
  262.  */
  263. void
  264. rhdMonitorPrintEDID(struct rhdMonitor *Monitor, xf86MonPtr EDID)
  265. {
  266.     xf86DrvMsg(EDID->scrnIndex, X_INFO, "EDID data for %s\n",
  267.                Monitor->Name);
  268.   xf86PrintEDID(EDID);
  269. }
  270.  
  271. /*
  272.  * Panels are the most complicated case we need to handle here.
  273.  * Information can come from several places, and we need to make sure
  274.  * that we end up with only the native resolution in our table.
  275.  */
  276. static struct rhdMonitor *
  277. rhdMonitorPanel(struct rhdConnector *Connector)
  278. {
  279.     struct rhdMonitor *Monitor;
  280.     DisplayModeRec *Mode = NULL;
  281.     xf86MonPtr EDID = NULL;
  282.  
  283.     RHDFUNC(Connector);
  284.  
  285.     /* has priority over AtomBIOS EDID */
  286.     if (Connector->DDC)
  287.     EDID = xf86DoEDID_DDC2(Connector->scrnIndex, Connector->DDC);
  288.  
  289. #ifdef ATOM_BIOS
  290.     {
  291.   RHDPtr rhdPtr = (RHDPtr)Connector->scrnIndex;
  292.         AtomBiosArgRec data;
  293.         AtomBiosResult Result;
  294.  
  295.   Result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  296.                                  ATOMBIOS_GET_PANEL_MODE, &data);
  297.         if (Result == ATOM_SUCCESS) {
  298.             Mode = data.mode;
  299.             Mode->type |= M_T_PREFERRED;
  300.         }
  301.         if (!EDID) {
  302.       Result = RHDAtomBiosFunc(rhdPtr,rhdPtr->atomBIOS,
  303.                                      ATOMBIOS_GET_PANEL_EDID, &data);
  304.             if (Result == ATOM_SUCCESS)
  305.     EDID = xf86InterpretEDID(rhdPtr, data.EDIDBlock);
  306.         }
  307.     }
  308. #endif
  309.  
  310.     Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
  311.  
  312.     Monitor->scrnIndex = Connector->scrnIndex;
  313.     Monitor->EDID      = EDID;
  314.  
  315.     if (Mode) {
  316.         Monitor->Name = xstrdup("LVDS Panel");
  317.     Monitor->Modes = RHDModesAdd(Monitor->Modes, Mode);
  318.         Monitor->NativeMode = Mode;
  319.     Monitor->numHSync = 1;
  320.     Monitor->HSync[0].lo = Mode->HSync;
  321.     Monitor->HSync[0].hi = Mode->HSync;
  322.     Monitor->numVRefresh = 1;
  323.     Monitor->VRefresh[0].lo = Mode->VRefresh;
  324.     Monitor->VRefresh[0].hi = Mode->VRefresh;
  325.     Monitor->Bandwidth = Mode->SynthClock;
  326.  
  327.         /* Clueless atombios does give us a mode, but doesn't give us a
  328.          * DPI or a size. It is just perfect, right? */
  329.         if (EDID) {
  330.       if (EDID->features.hsize)
  331.         Monitor->xDpi = (Mode->HDisplay * 2.54) / ((float) EDID->features.hsize) + 0.5;
  332.       if (EDID->features.vsize)
  333.         Monitor->yDpi = (Mode->VDisplay * 2.54) / ((float) EDID->features.vsize) + 0.5;
  334.     }
  335.     } else if (EDID) {
  336.       RHDMonitorEDIDSet(Monitor, EDID);
  337.       rhdPanelEDIDModesFilter(Monitor);
  338.     } else {
  339.         xf86DrvMsg(Connector->scrnIndex, X_ERROR,
  340.                    "%s: No panel mode information found.\n", __func__);
  341.         xfree(Monitor);
  342.       return NULL;
  343.     }
  344.  
  345.     /* panel should be driven at native resolution only. */
  346.   Monitor->UseFixedModes = TRUE;
  347.   Monitor->ReducedAllowed = TRUE;
  348.  
  349.   if (EDID)
  350.     rhdMonitorPrintEDID(Monitor, EDID);
  351.  
  352.   return Monitor;
  353. }
  354.  
  355. /*
  356.  * rhdMonitorTV(): get TV modes. Currently we can only get this from AtomBIOS.
  357.  */
  358. static struct rhdMonitor *
  359. rhdMonitorTV(struct rhdConnector *Connector)
  360. {
  361.     struct rhdMonitor *Monitor = NULL;
  362. #ifdef ATOM_BIOS
  363.     RHDPtr rhdPtr = RHDPTRI(Connector);
  364.     DisplayModeRec *Mode = NULL;
  365.     AtomBiosArgRec arg;
  366.  
  367.     RHDFUNC(Connector);
  368.  
  369.     arg.tvMode = rhdPtr->tvMode;
  370.     if (RHDAtomBiosFunc(Connector->scrnIndex, rhdPtr->atomBIOS,
  371.                         ATOM_ANALOG_TV_MODE, &arg)
  372.         != ATOM_SUCCESS)
  373.         return NULL;
  374.  
  375.     Mode = arg.mode;
  376.     Mode->type |= M_T_PREFERRED;
  377.  
  378.     Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
  379.  
  380.     Monitor->scrnIndex = Connector->scrnIndex;
  381.     Monitor->EDID      = NULL;
  382.  
  383.     Monitor->Name      = xstrdup("TV");
  384.     Monitor->Modes     = RHDModesAdd(Monitor->Modes, Mode);
  385.     Monitor->NativeMode= Mode;
  386.     Monitor->numHSync  = 1;
  387.     Monitor->HSync[0].lo = Mode->HSync;
  388.     Monitor->HSync[0].hi = Mode->HSync;
  389.     Monitor->numVRefresh = 1;
  390.     Monitor->VRefresh[0].lo = Mode->VRefresh;
  391.     Monitor->VRefresh[0].hi = Mode->VRefresh;
  392.     Monitor->Bandwidth = Mode->SynthClock;
  393.  
  394.     /* TV should be driven at native resolution only. */
  395.     Monitor->UseFixedModes = TRUE;
  396.     Monitor->ReducedAllowed = FALSE;
  397.     /*
  398.      *  hack: the TV encoder takes care of that.
  399.      *  The mode that goes in isn't what comes out.
  400.      */
  401.     Mode->Flags &= ~(V_INTERLACE);
  402. #endif
  403.     return Monitor;
  404. }
  405.  
  406. /*
  407.  *
  408.  */
  409. struct rhdMonitor *
  410. RHDMonitorInit(struct rhdConnector *Connector)
  411. {
  412.   struct rhdMonitor *Monitor = NULL;
  413.  
  414.   RHDFUNC(Connector);
  415.  
  416.   if (Connector->Type == RHD_CONNECTOR_PANEL)
  417.     Monitor = rhdMonitorPanel(Connector);
  418.     else if (Connector->Type == RHD_CONNECTOR_TV)
  419.         Monitor = rhdMonitorTV(Connector);
  420.     else if (Connector->DDC) {
  421.     xf86MonPtr EDID = xf86DoEDID_DDC2(Connector->scrnIndex, Connector->DDC);
  422.         if (EDID) {
  423.             Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
  424.         Monitor->scrnIndex = Connector->scrnIndex;
  425.         Monitor->EDID   = EDID;
  426.             Monitor->NativeMode = NULL;
  427.  
  428.         RHDMonitorEDIDSet(Monitor, EDID);
  429.         rhdMonitorPrintEDID(Monitor, EDID);
  430.       }
  431.     }
  432.   return Monitor;
  433. }
  434.  
  435. /*
  436.  *
  437.  */
  438. void
  439. RHDMonitorDestroy(struct rhdMonitor *Monitor)
  440. {
  441.     DisplayModePtr Mode, Next;
  442.  
  443.     for (Mode = Monitor->Modes; Mode;) {
  444.         Next = Mode->next;
  445.  
  446.         xfree(Mode->name);
  447.         xfree(Mode);
  448.  
  449.         Mode = Next;
  450.     }
  451.  
  452.     if (Monitor->EDID)
  453.         xfree(Monitor->EDID->rawData);
  454.     xfree(Monitor->EDID);
  455.     xfree(Monitor->Name);
  456.     xfree(Monitor);
  457. }
  458.  
  459.  
  460. static unsigned char * VDIFRead(RHDPtr rhdPtr, I2CBusPtr pBus, int start);
  461.  
  462. #define RETRIES 4
  463.  
  464. static xf86VdifLimitsPtr* get_limits(CARD8 *c);
  465. static xf86VdifGammaPtr* get_gamma(CARD8 *c);
  466. static xf86VdifTimingPtr* get_timings(CARD8 *c);
  467.  
  468. xf86vdifPtr xf86InterpretVdif(CARD8 *c)
  469. {
  470.   xf86VdifPtr p = (xf86VdifPtr)c;
  471.   xf86vdifPtr vdif;
  472.   int i;
  473.  
  474.   unsigned long l = 0;
  475.  
  476.   if (c == NULL) return NULL;
  477.   if (p->VDIFId[0] != 'V' || p->VDIFId[1] != 'D' || p->VDIFId[2] != 'I'
  478.       || p->VDIFId[3] != 'F') return NULL;
  479.   for ( i = 12; i < p->FileLength; i++)
  480.     l += c[i];
  481.   if ( l != p->Checksum) return NULL;
  482.   vdif = malloc(sizeof(xf86vdif));
  483.   vdif->vdif = p;
  484.   vdif->limits = get_limits(c);
  485.   vdif->timings = get_timings(c);
  486.   vdif->gamma = get_gamma(c);
  487.   vdif->strings = VDIF_STRING(((xf86VdifPtr)c),0);
  488.   free(c);
  489.   return vdif;
  490. }
  491.  
  492. static xf86VdifLimitsPtr*
  493. get_limits(CARD8 *c)
  494. {
  495.     int num, i, j;
  496.     xf86VdifLimitsPtr *pp;
  497.     xf86VdifLimitsPtr p;
  498.  
  499.     num = ((xf86VdifPtr)c)->NumberOperationalLimits;
  500.     pp = malloc(sizeof(xf86VdifLimitsPtr) * (num+1));
  501.     p = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c));
  502.     j = 0;
  503.     for ( i = 0; i<num; i++) {
  504.         if (p->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG)
  505.             pp[j++] = p;
  506.         VDIF_NEXT_OPERATIONAL_LIMITS(p);
  507.     }
  508.     pp[j] = NULL;
  509.     return pp;
  510. }
  511.  
  512. static xf86VdifGammaPtr*
  513. get_gamma(CARD8 *c)
  514. {
  515.     int num, i, j;
  516.     xf86VdifGammaPtr *pp;
  517.     xf86VdifGammaPtr p;
  518.  
  519.     num = ((xf86VdifPtr)c)->NumberOptions;
  520.     pp = malloc(sizeof(xf86VdifGammaPtr) * (num+1));
  521.     p = (xf86VdifGammaPtr)VDIF_OPTIONS(((xf86VdifPtr)c));
  522.     j = 0;
  523.     for ( i = 0; i<num; i++)
  524.     {
  525.         if (p->Header.ScnTag == VDIF_GAMMA_TABLE_TAG)
  526.             pp[j++] = p;
  527.         VDIF_NEXT_OPTIONS(p);
  528.     }
  529.     pp[j] = NULL;
  530.     return pp;
  531. }
  532.  
  533. static xf86VdifTimingPtr*
  534. get_timings(CARD8 *c)
  535. {
  536.     int num, num_limits;
  537.     int i,j,k;
  538.     xf86VdifLimitsPtr lp;
  539.     xf86VdifTimingPtr *pp;
  540.     xf86VdifTimingPtr p;
  541.  
  542.     num = ((xf86VdifPtr)c)->NumberOperationalLimits;
  543.     lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c));
  544.     num_limits = 0;
  545.     for (i = 0; i < num; i++) {
  546.         if (lp->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG)
  547.             num_limits += lp->NumberPreadjustedTimings;
  548.         VDIF_NEXT_OPERATIONAL_LIMITS(lp);
  549.     }
  550.     pp = malloc(sizeof(xf86VdifTimingPtr)
  551.                                       * (num_limits+1));
  552.     j = 0;
  553.     lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr) c));
  554.     for (i = 0; i < num; i++) {
  555.         p = VDIF_PREADJUSTED_TIMING(lp);
  556.         for (k = 0; k < lp->NumberPreadjustedTimings; k++) {
  557.             if (p->Header.ScnTag == VDIF_PREADJUSTED_TIMING_TAG)
  558.                 pp[j++] = p;
  559.             VDIF_NEXT_PREADJUSTED_TIMING(p);
  560.         }
  561.         VDIF_NEXT_OPERATIONAL_LIMITS(lp);
  562.     }
  563.     pp[j] = NULL;
  564.     return pp;
  565. }
  566.  
  567. int DDC_checksum(unsigned char *block, int len)
  568. {
  569.   int i, result = 0;
  570.   int not_null = 0;
  571.  
  572.   for (i=0;i<len;i++)
  573.   {
  574.     not_null |= block[i];
  575.     result += block[i];
  576.   }
  577.  
  578.   if (result & 0xFF) DBG(dbgprintf("DDC checksum not correct\n"));
  579.   if (!not_null) DBG(dbgprintf("DDC read all Null\n"));
  580.  
  581.     /* catch the trivial case where all bytes are 0 */
  582.   if (!not_null) return 1;
  583.  
  584.   return (result&0xFF);
  585. }
  586.  
  587. static unsigned char *
  588. DDCRead_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus, int start, int len)
  589. {
  590.   I2CDevPtr dev;
  591.   unsigned char W_Buffer[2];
  592.   int w_bytes;
  593.   unsigned char *R_Buffer;
  594.   int i;
  595.  
  596.   RHDFUNC(rhdPtr);
  597.  
  598. //    xf86LoaderReqSymLists(i2cSymbols, NULL);
  599.  
  600.   if (!(dev = xf86I2CFindDev(pBus, 0x00A0)))
  601.   {
  602.     dev = xf86CreateI2CDevRec();
  603.     dev->DevName = "ddc2";
  604.     dev->SlaveAddr = 0xA0;
  605.     dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
  606.     dev->StartTimeout = 550;
  607.     dev->BitTimeout = 40;
  608.     dev->ByteTimeout = 40;
  609.     dev->AcknTimeout = 40;
  610.  
  611.     dev->pI2CBus = pBus;
  612.     if (!xf86I2CDevInit(dev))
  613.     {
  614.       DBG(dbgprintf("No DDC2 device\n"));
  615.             return NULL;
  616.     }
  617.   }
  618.   if (start < 0x100)
  619.   {
  620.     w_bytes = 1;
  621.     W_Buffer[0] = start;
  622.   }
  623.   else
  624.   {
  625.     w_bytes = 2;
  626.     W_Buffer[0] = start & 0xFF;
  627.     W_Buffer[1] = (start & 0xFF00) >> 8;
  628.   }
  629.  
  630.   R_Buffer = calloc(1,sizeof(unsigned char)* (len));
  631.  
  632.   if( !R_Buffer)
  633.   {
  634.     DBG(dbgprintf("R_Buffer = NULL\n"));
  635.     return NULL;
  636.   };
  637.  
  638.   for (i=0; i<RETRIES; i++)
  639.   {
  640.     if (xf86I2CWriteRead(dev, W_Buffer,w_bytes, R_Buffer,len))
  641.     {
  642.             if (!DDC_checksum(R_Buffer,len))
  643.         return R_Buffer;
  644.       else
  645.         DBG(dbgprintf("Checksum error in EDID block\n"));
  646.     }
  647.     else
  648.       DBG(dbgprintf("Error reading EDID block\n"));
  649.   }
  650.   xf86DestroyI2CDevRec(dev,TRUE);
  651.   free(R_Buffer);
  652.   return NULL;
  653. }
  654.  
  655. static unsigned char*
  656. EDID1Read_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus)
  657. {
  658.     return  DDCRead_DDC2(rhdPtr, pBus, 0, EDID1_LEN);
  659. }
  660.  
  661. xf86MonPtr
  662. xf86DoEDID_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus)
  663. {
  664.   unsigned char *EDID_block = NULL;
  665.   unsigned char *VDIF_Block = NULL;
  666.   xf86MonPtr tmp = NULL;
  667.  
  668.   RHDFUNC(rhdPtr);
  669.  
  670.   EDID_block = EDID1Read_DDC2(rhdPtr,pBus);
  671.  
  672.   if (EDID_block)
  673.   {
  674.     tmp = xf86InterpretEDID(rhdPtr,EDID_block);
  675.   }
  676.   else
  677.   {
  678.     DBG(dbgprintf("No EDID block returned\n"));
  679.     return NULL;
  680.   }
  681.  
  682.   if (!tmp)
  683.   {
  684.     DBG(dbgprintf("Cannot interpret EDID block\n"));
  685.     return tmp;
  686.   }
  687.   DBG(dbgprintf("Sections to follow: %d\n",tmp->no_sections));
  688.  
  689.   VDIF_Block =
  690.   VDIFRead(rhdPtr, pBus, EDID1_LEN * (tmp->no_sections + 1));
  691.   tmp->vdif = xf86InterpretVdif(VDIF_Block);
  692.  
  693.   return tmp;
  694. }
  695.  
  696. static unsigned char*
  697. VDIFRead(RHDPtr rhdPtr, I2CBusPtr pBus, int start)
  698. {
  699.   unsigned char * Buffer, *v_buffer = NULL, *v_bufferp = NULL;
  700.   int i, num = 0;
  701.  
  702.     /* read VDIF length in 64 byte blocks */
  703.   Buffer = DDCRead_DDC2(rhdPtr, pBus,start,64);
  704.   if (Buffer == NULL)
  705.     return NULL;
  706.  
  707.   DBG(dbgprintf("number of 64 bit blocks: %i\n",Buffer[0]));
  708.  
  709.   if ((num = Buffer[0]) > 0)
  710.     v_buffer = v_bufferp = malloc(sizeof(unsigned char) * 64 * num);
  711.  
  712.   for (i = 0; i < num; i++)
  713.   {
  714.     Buffer = DDCRead_DDC2(rhdPtr, pBus,start,64);
  715.     if (Buffer == NULL)
  716.     {
  717.       free (v_buffer);
  718.             return NULL;
  719.     }
  720.     memcpy(v_bufferp,Buffer,63); /* 64th byte is checksum */
  721.     free(Buffer);
  722.     v_bufferp += 63;
  723.   }
  724.   return v_buffer;
  725. }
  726.  
  727.  
  728.  
  729. static void print_vendor(RHDPtr rhdPtr, struct vendor *);
  730. static void print_version(RHDPtr rhdPtr, struct edid_version *);
  731. static void print_display(RHDPtr rhdPtr, struct disp_features *,
  732.                           struct edid_version *);
  733. static void print_established_timings(RHDPtr rhdPtr,
  734.                                       struct established_timings *);
  735. static void print_std_timings(RHDPtr rhdPtr, struct std_timings *);
  736. static void print_detailed_monitor_section(RHDPtr rhdPtr,
  737.                                            struct detailed_monitor_section *);
  738. static void print_detailed_timings(RHDPtr rhdPtr, struct detailed_timings *);
  739.  
  740. static void print_input_features(RHDPtr rhdPtr, struct disp_features *);
  741. static void print_dpms_features(RHDPtr rhdPtr, struct disp_features *,
  742.                                 struct edid_version *v);
  743. static void print_whitepoint(RHDPtr rhdPtr, struct disp_features *);
  744. static void print_number_sections(RHDPtr rhdPtr, int);
  745.  
  746. xf86MonPtr
  747. xf86PrintEDID(xf86MonPtr m)
  748. {
  749.     if (!(m)) return NULL;
  750.     print_vendor(m->rhdPtr,&m->vendor);
  751.     print_version(m->rhdPtr,&m->ver);
  752.     print_display(m->rhdPtr,&m->features, &m->ver);
  753.     print_established_timings(m->rhdPtr,&m->timings1);
  754.     print_std_timings(m->rhdPtr,m->timings2);
  755.     print_detailed_monitor_section(m->rhdPtr,m->det_mon);
  756.     print_number_sections(m->rhdPtr,m->no_sections);
  757.  
  758.     return m;
  759. }
  760.  
  761. static void
  762. print_vendor(RHDPtr rhdPtr, struct vendor *c)
  763. {
  764.   DBG(dbgprintf("Manufacturer: %s  Model: %x  Serial#: %u\n",
  765.             (char *)&c->name, c->prod_id, c->serial));
  766.   DBG(dbgprintf("Year: %u  Week: %u\n", c->year, c->week));
  767. }
  768.  
  769. static void
  770. print_version(RHDPtr rhdPtr, struct edid_version *c)
  771. {
  772.   DBG(dbgprintf("EDID Version: %u.%u\n",c->version,c->revision));
  773. }
  774.  
  775. static void
  776. print_display(RHDPtr rhdPtr, struct disp_features *disp,
  777.               struct edid_version *version)
  778. {
  779.     print_input_features(rhdPtr,disp);
  780.     DBG(dbgprintf("Max H-Image Size [cm]: "));
  781.     if (disp->hsize)
  782.       DBG(dbgprintf("horiz.: %i  ",disp->hsize));
  783.     else
  784.       DBG(dbgprintf("H-Size may change,  "));
  785.     if (disp->vsize)
  786.       DBG(dbgprintf("vert.: %i\n",disp->vsize));
  787.     else
  788.       DBG(dbgprintf("V-Size may change\n"));
  789.     DBG(dbgprintf("Gamma: %.2f\n", (double)disp->gamma));
  790.     print_dpms_features(rhdPtr,disp,version);
  791.     print_whitepoint(rhdPtr,disp);
  792. }
  793.  
  794. static void
  795. print_input_features(RHDPtr rhdPtr, struct disp_features *c)
  796. {
  797.     if (DIGITAL(c->input_type))
  798.     {
  799.       DBG(dbgprintf("Digital Display Input\n"));
  800.       if (DFP1(c->input_dfp))
  801.         DBG(dbgprintf("DFP 1.x compatible TMDS\n"));
  802.     }
  803.     else
  804.     {
  805.       DBG(dbgprintf("Analog Display Input,  "));
  806.       DBG(dbgprintf("Input Voltage Level: "));
  807.       switch (c->input_voltage)
  808.       {
  809.         case V070:
  810.           DBG(dbgprintf("0.700/0.300 V\n"));
  811.           break;
  812.         case V071:
  813.           DBG(dbgprintf("0.714/0.286 V\n"));
  814.           break;
  815.         case V100:
  816.           DBG(dbgprintf("1.000/0.400 V\n"));
  817.           break;
  818.         case V007:
  819.           DBG(dbgprintf("0.700/0.700 V\n"));
  820.           break;
  821.         default:
  822.           DBG(dbgprintf("undefined\n"));
  823.       }
  824.       if (SIG_SETUP(c->input_setup))
  825.         DBG(dbgprintf("Signal levels configurable\n"));
  826.       DBG(dbgprintf("Sync:"));
  827.       if (SEP_SYNC(c->input_sync))
  828.         DBG(dbgprintf("  Separate"));
  829.       if (COMP_SYNC(c->input_sync))
  830.         DBG(dbgprintf("  Composite"));
  831.       if (SYNC_O_GREEN(c->input_sync))
  832.         DBG(dbgprintf("  SyncOnGreen"));
  833.       if (SYNC_SERR(c->input_sync))
  834.         DBG(dbgprintf("Serration on. "
  835.          "V.Sync Pulse req. if CompSync or SyncOnGreen\n"));
  836.       else
  837.         DBG(dbgprintf("\n"));
  838.     }
  839. }
  840.  
  841. static void
  842. print_dpms_features(RHDPtr rhdPtr, struct disp_features *c,
  843.                     struct edid_version *v)
  844. {
  845.    if (c->dpms)
  846.    {
  847.      DBG(dbgprintf("DPMS capabilities:"));
  848.      if (DPMS_STANDBY(c->dpms))
  849.        DBG(dbgprintf(" StandBy"));
  850.      if (DPMS_SUSPEND(c->dpms))
  851.        DBG(dbgprintf(" Suspend"));
  852.      if (DPMS_OFF(c->dpms))
  853.        DBG(dbgprintf(" Off"));
  854.    }
  855.    else
  856.      DBG(dbgprintf("No DPMS capabilities specified"));
  857.    switch (c->display_type)
  858.    {
  859.      case DISP_MONO:
  860.        DBG(dbgprintf("; Monochorome/GrayScale Display\n"));
  861.        break;
  862.      case DISP_RGB:
  863.        DBG(dbgprintf("; RGB/Color Display\n"));
  864.        break;
  865.      case DISP_MULTCOLOR:
  866.        DBG(dbgprintf("; Non RGB Multicolor Display\n"));
  867.        break;
  868.      default:
  869.        DBG(dbgprintf("\n"));
  870.        break;
  871.    }
  872.    if (STD_COLOR_SPACE(c->msc))
  873.      DBG(dbgprintf("Default color space is primary color space\n"));
  874.    if (PREFERRED_TIMING_MODE(c->msc))
  875.      DBG(dbgprintf("First detailed timing is preferred mode\n"));
  876.    else
  877.      if (v->version == 1 && v->revision >= 3)
  878.        DBG(dbgprintf("First detailed timing not preferred "
  879.                  "mode in violation of standard!"));
  880.    if (GFT_SUPPORTED(c->msc))
  881.      DBG(dbgprintf("GTF timings supported\n"));
  882. }
  883.  
  884. static void
  885. print_whitepoint(RHDPtr rhdPtr, struct disp_features *disp)
  886. {
  887.     DBG(dbgprintf("redX: %.3f redY: %.3f   ",
  888.          (double)disp->redx,(double)disp->redy));
  889.     DBG(dbgprintf("greenX: %.3f greenY: %.3f\n",
  890.          (double)disp->greenx,(double)disp->greeny));
  891.     DBG(dbgprintf("blueX: %.3f blueY: %.3f   ",
  892.          (double)disp->bluex,(double)disp->bluey));
  893.     DBG(dbgprintf("whiteX: %.3f whiteY: %.3f\n",
  894.          (double)disp->whitex,(double)disp->whitey));
  895. }
  896.  
  897. static void
  898. print_established_timings(RHDPtr rhdPtr, struct established_timings *t)
  899. {
  900.     unsigned char c;
  901.  
  902.     if (t->t1 || t->t2 || t->t_manu)
  903.       DBG(dbgprintf("Supported VESA Video Modes:\n"));
  904.     c=t->t1;
  905.     if (c&0x80) DBG(dbgprintf("720x400@70Hz\n"));
  906.     if (c&0x40) DBG(dbgprintf("720x400@88Hz\n"));
  907.     if (c&0x20) DBG(dbgprintf("640x480@60Hz\n"));
  908.     if (c&0x10) DBG(dbgprintf("640x480@67Hz\n"));
  909.     if (c&0x08) DBG(dbgprintf("640x480@72Hz\n"));
  910.     if (c&0x04) DBG(dbgprintf("640x480@75Hz\n"));
  911.     if (c&0x02) DBG(dbgprintf("800x600@56Hz\n"));
  912.     if (c&0x01) DBG(dbgprintf("800x600@60Hz\n"));
  913.     c=t->t2;
  914.     if (c&0x80) DBG(dbgprintf("800x600@72Hz\n"));
  915.     if (c&0x40) DBG(dbgprintf("800x600@75Hz\n"));
  916.     if (c&0x20) DBG(dbgprintf("832x624@75Hz\n"));
  917.     if (c&0x10) DBG(dbgprintf("1024x768@87Hz (interlaced)\n"));
  918.     if (c&0x08) DBG(dbgprintf("1024x768@60Hz\n"));
  919.     if (c&0x04) DBG(dbgprintf("1024x768@70Hz\n"));
  920.     if (c&0x02) DBG(dbgprintf("1024x768@75Hz\n"));
  921.     if (c&0x01) DBG(dbgprintf("1280x1024@75Hz\n"));
  922.     c=t->t_manu;
  923.     if (c&0x80) DBG(dbgprintf("1152x870@75Hz\n"));
  924.     DBG(dbgprintf("Manufacturer's mask: %X\n",c&0x7F));
  925. }
  926.  
  927. static void
  928. print_std_timings(RHDPtr rhdPtr, struct std_timings *t)
  929. {
  930.     int i;
  931.     char done = 0;
  932.     for (i=0;i<STD_TIMINGS;i++)
  933.     {
  934.       if (t[i].hsize > 256)   /* sanity check */
  935.       {
  936.         if (!done)
  937.         {
  938.           DBG(dbgprintf("Supported Future Video Modes:\n"));
  939.           done = 1;
  940.         }
  941.         DBG(dbgprintf("#%d: hsize: %i  vsize %i  refresh: %i  vid: %i\n",
  942.                       i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id));
  943.       }
  944.     }
  945. }
  946.  
  947. static void
  948. print_detailed_monitor_section(RHDPtr rhdPtr,
  949.                                struct detailed_monitor_section *m)
  950. {
  951.   int i,j;
  952.  
  953.   for (i=0;i<DET_TIMINGS;i++)
  954.   {
  955.     switch (m[i].type)
  956.     {
  957.       case DT:
  958.         print_detailed_timings(rhdPtr,&m[i].section.d_timings);
  959.         break;
  960.       case DS_SERIAL:
  961.         DBG(dbgprintf("Serial No: %s\n",m[i].section.serial));
  962.         break;
  963.       case DS_ASCII_STR:
  964.         DBG(dbgprintf(" %s\n",m[i].section.ascii_data));
  965.         break;
  966.       case DS_NAME:
  967.         DBG(dbgprintf("Monitor name: %s\n",m[i].section.name));
  968.         break;
  969.       case DS_RANGES:
  970.         DBG(dbgprintf("Ranges: V min: %i  V max: %i Hz, H min: %i  H max: %i kHz,",
  971.                    m[i].section.ranges.min_v, m[i].section.ranges.max_v,
  972.                    m[i].section.ranges.min_h, m[i].section.ranges.max_h));
  973.         if (m[i].section.ranges.max_clock != 0)
  974.           DBG(dbgprintf(" PixClock max %i MHz\n",m[i].section.ranges.max_clock));
  975.         else
  976.           DBG(dbgprintf("\n"));
  977.         if (m[i].section.ranges.gtf_2nd_f > 0)
  978.           DBG(dbgprintf(" 2nd GTF parameters: f: %i kHz "
  979.                     "c: %i m: %i k %i j %i\n",
  980.                     m[i].section.ranges.gtf_2nd_f,
  981.                     m[i].section.ranges.gtf_2nd_c,
  982.                     m[i].section.ranges.gtf_2nd_m,
  983.                     m[i].section.ranges.gtf_2nd_k,
  984.                     m[i].section.ranges.gtf_2nd_j));
  985.           break;
  986.       case DS_STD_TIMINGS:
  987.         for (j = 0; j<5; j++)
  988.           DBG(dbgprintf("#%i: hsize: %i  vsize %i  refresh: %i  "
  989.                     "vid: %i\n",i,m[i].section.std_t[i].hsize,
  990.                     m[i].section.std_t[j].vsize,m[i].section.std_t[j].refresh,
  991.                     m[i].section.std_t[j].id));
  992.           break;
  993.       case DS_WHITE_P:
  994.         for (j = 0; j<2; j++)
  995.           if (m[i].section.wp[j].index != 0)
  996.             DBG(dbgprintf("White point %i: whiteX: %f, whiteY: %f; gamma: %f\n",
  997.                       m[i].section.wp[j].index,(double)m[i].section.wp[j].white_x,
  998.                       (double)m[i].section.wp[j].white_y,
  999.                       (double)m[i].section.wp[j].white_gamma));
  1000.             break;
  1001.       case DS_DUMMY:
  1002.       default:
  1003.         break;
  1004.     }
  1005.   }
  1006. }
  1007.  
  1008. static void
  1009. print_detailed_timings(RHDPtr rhdPtr, struct detailed_timings *t)
  1010. {
  1011.  
  1012.     if (t->clock > 15000000)  /* sanity check */
  1013.     {
  1014.       DBG(dbgprintf("Supported additional Video Mode:\n"));
  1015.       DBG(dbgprintf("clock: %.1f MHz   ",(double)t->clock/1000000.0));
  1016.       DBG(dbgprintf("Image Size:  %i x %i mm\n",t->h_size,t->v_size));
  1017.       DBG(dbgprintf("h_active: %i  h_sync: %i  h_sync_end %i h_blank_end %i ",
  1018.                     t->h_active, t->h_sync_off + t->h_active,
  1019.                     t->h_sync_off + t->h_sync_width + t->h_active,
  1020.                     t->h_active + t->h_blanking));
  1021.       DBG(dbgprintf("h_border: %i\n",t->h_border));
  1022.       DBG(dbgprintf("v_active: %i  v_sync: %i  v_sync_end %i v_blanking: %i ",
  1023.                     t->v_active, t->v_sync_off + t->v_active,
  1024.                     t->v_sync_off + t->v_sync_width + t->v_active,
  1025.                     t->v_active + t->v_blanking));
  1026.       DBG(dbgprintf("v_border: %i\n",t->v_border));
  1027.       if (IS_STEREO(t->stereo))
  1028.       {
  1029.         DBG(dbgprintf("Stereo: "));
  1030.         if (IS_RIGHT_STEREO(t->stereo))
  1031.         {
  1032.           if (!t->stereo_1)
  1033.             DBG(dbgprintf("right channel on sync\n"));
  1034.           else
  1035.             DBG(dbgprintf("left channel on sync\n"));
  1036.         }
  1037.         else
  1038.           if (IS_LEFT_STEREO(t->stereo))
  1039.           {
  1040.             if (!t->stereo_1)
  1041.               DBG(dbgprintf("right channel on even line\n"));
  1042.             else
  1043.               DBG(dbgprintf("left channel on evel line\n"));
  1044.           }
  1045.         if (IS_4WAY_STEREO(t->stereo))
  1046.         {
  1047.           if (!t->stereo_1)
  1048.             DBG(dbgprintf("4-way interleaved\n"));
  1049.           else
  1050.             DBG(dbgprintf("side-by-side interleaved"));
  1051.         }
  1052.       }
  1053.     }
  1054. }
  1055.  
  1056. static void
  1057. print_number_sections(RHDPtr rhdPtr, int num)
  1058. {
  1059.   if (num)
  1060.     DBG(dbgprintf("Number of EDID sections to follow: %i\n",num));
  1061. }
  1062.  
  1063.  
  1064.  
  1065. static void get_vendor_section(Uchar*, struct vendor *);
  1066. static void get_version_section(Uchar*, struct edid_version *);
  1067. static void get_display_section(Uchar*, struct disp_features *,
  1068.                                 struct edid_version *);
  1069. static void get_established_timing_section(Uchar*, struct established_timings *);
  1070. static void get_std_timing_section(Uchar*, struct std_timings *,
  1071.                                    struct edid_version *);
  1072. static void get_dt_md_section(Uchar *, struct edid_version *,
  1073.                               struct detailed_monitor_section *det_mon);
  1074. static void copy_string(Uchar *, Uchar *);
  1075. static void get_dst_timing_section(Uchar *, struct std_timings *,
  1076.                                    struct edid_version *);
  1077. static void get_monitor_ranges(Uchar *, struct monitor_ranges *);
  1078. static void get_whitepoint_section(Uchar *, struct whitePoints *);
  1079. static void get_detailed_timing_section(Uchar*, struct  detailed_timings *);
  1080. static Bool validate_version(RHDPtr rhdPtr, struct edid_version *);
  1081.  
  1082.  
  1083. xf86MonPtr
  1084. xf86InterpretEDID(int scrnIndex, Uchar *block)
  1085. {
  1086.     xf86MonPtr m;
  1087.     RHDPtr rhdPtr = (RHDPtr)scrnIndex;
  1088.  
  1089.     if (!block) return NULL;
  1090.     if (! (m = calloc(sizeof(xf86Monitor),1))) return NULL;
  1091.     m->rhdPtr = rhdPtr;
  1092.     m->rawData = block;
  1093.  
  1094.     get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor);
  1095.     get_version_section(SECTION(VERSION_SECTION,block),&m->ver);
  1096.     if (!validate_version(rhdPtr, &m->ver)) goto error;
  1097.     get_display_section(SECTION(DISPLAY_SECTION,block),&m->features,
  1098.                         &m->ver);
  1099.     get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block),
  1100.                                    &m->timings1);
  1101.     get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
  1102.                            &m->ver);
  1103.     get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
  1104.     m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
  1105.  
  1106.     return (m);
  1107.  
  1108.  error:
  1109.     free(m);
  1110.     return NULL;
  1111. }
  1112.  
  1113. static void
  1114. get_vendor_section(Uchar *c, struct vendor *r)
  1115. {
  1116.     r->name[0] = L1;
  1117.     r->name[1] = L2;
  1118.     r->name[2] = L3;
  1119.     r->name[3] = '\0';
  1120.  
  1121.     r->prod_id = PROD_ID;
  1122.     r->serial  = SERIAL_NO;
  1123.     r->week    = WEEK;
  1124.     r->year    = YEAR;
  1125. }
  1126.  
  1127. static void
  1128. get_version_section(Uchar *c, struct edid_version *r)
  1129. {
  1130.     r->version  = VERSION;
  1131.     r->revision = REVISION;
  1132. }
  1133.  
  1134. static void
  1135. get_display_section(Uchar *c, struct disp_features *r,
  1136.                     struct edid_version *v)
  1137. {
  1138.     r->input_type = INPUT_TYPE;
  1139.     if (!DIGITAL(r->input_type))
  1140.     {
  1141.       r->input_voltage = INPUT_VOLTAGE;
  1142.       r->input_setup = SETUP;
  1143.       r->input_sync = SYNC;
  1144.     }
  1145.     else
  1146.       if (v->version > 1 || v->revision > 2)
  1147.         r->input_dfp = DFP;
  1148.     r->hsize = HSIZE_MAX;
  1149.     r->vsize = VSIZE_MAX;
  1150.     r->gamma = GAMMA;
  1151.     r->dpms =  DPMS;
  1152.     r->display_type = DISPLAY_TYPE;
  1153.     r->msc = MSC;
  1154.     r->redx = REDX;
  1155.     r->redy = REDY;
  1156.     r->greenx = GREENX;
  1157.     r->greeny = GREENY;
  1158.     r->bluex = BLUEX;
  1159.     r->bluey = BLUEY;
  1160.     r->whitex = WHITEX;
  1161.     r->whitey = WHITEY;
  1162. }
  1163.  
  1164. static void
  1165. get_established_timing_section(Uchar *c, struct established_timings *r)
  1166. {
  1167.     r->t1 = T1;
  1168.     r->t2 = T2;
  1169.     r->t_manu = T_MANU;
  1170. }
  1171.  
  1172. static void
  1173. get_std_timing_section(Uchar *c, struct std_timings *r,
  1174.                        struct edid_version *v)
  1175. {
  1176.     int i;
  1177.  
  1178.     for (i=0;i<STD_TIMINGS;i++)
  1179.     {
  1180.       if (VALID_TIMING)
  1181.       {
  1182.         r[i].hsize = HSIZE1;
  1183.         VSIZE1(r[i].vsize);
  1184.         r[i].refresh = REFRESH_R;
  1185.         r[i].id = STD_TIMING_ID;
  1186.       }
  1187.       else
  1188.       {
  1189.         r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0;
  1190.        }
  1191.        NEXT_STD_TIMING;
  1192.     }
  1193. }
  1194.  
  1195. static void
  1196. get_dt_md_section(Uchar *c, struct edid_version *ver,
  1197.                   struct detailed_monitor_section *det_mon)
  1198. {
  1199.   int i;
  1200.  
  1201.   for (i=0;i<DET_TIMINGS;i++) {
  1202.     if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) {
  1203.  
  1204.       switch (MONITOR_DESC_TYPE) {
  1205.       case SERIAL_NUMBER:
  1206.         det_mon[i].type = DS_SERIAL;
  1207.         copy_string(c,det_mon[i].section.serial);
  1208.         break;
  1209.       case ASCII_STR:
  1210.         det_mon[i].type = DS_ASCII_STR;
  1211.         copy_string(c,det_mon[i].section.ascii_data);
  1212.         break;
  1213.       case MONITOR_RANGES:
  1214.         det_mon[i].type = DS_RANGES;
  1215.         get_monitor_ranges(c,&det_mon[i].section.ranges);
  1216.         break;
  1217.       case MONITOR_NAME:
  1218.         det_mon[i].type = DS_NAME;
  1219.         copy_string(c,det_mon[i].section.name);
  1220.         break;
  1221.       case ADD_COLOR_POINT:
  1222.         det_mon[i].type = DS_WHITE_P;
  1223.         get_whitepoint_section(c,det_mon[i].section.wp);
  1224.         break;
  1225.       case ADD_STD_TIMINGS:
  1226.         det_mon[i].type = DS_STD_TIMINGS;
  1227.         get_dst_timing_section(c,det_mon[i].section.std_t, ver);
  1228.         break;
  1229.       case ADD_DUMMY:
  1230.         det_mon[i].type = DS_DUMMY;
  1231.         break;
  1232.       }
  1233.     } else {
  1234.       det_mon[i].type = DT;
  1235.       get_detailed_timing_section(c,&det_mon[i].section.d_timings);
  1236.     }
  1237.     NEXT_DT_MD_SECTION;
  1238.   }
  1239. }
  1240.  
  1241. static void
  1242. copy_string(Uchar *c, Uchar *s)
  1243. {
  1244.   int i;
  1245.   c = c + 5;
  1246.   for (i = 0; (i < 13 && *c != 0x0A); i++)
  1247.     *(s++) = *(c++);
  1248.   *s = 0;
  1249.   while (i-- && (*--s == 0x20)) *s = 0;
  1250. }
  1251.  
  1252. static void
  1253. get_dst_timing_section(Uchar *c, struct std_timings *t,
  1254.                        struct edid_version *v)
  1255. {
  1256.   int j;
  1257.     c = c + 5;
  1258.     for (j = 0; j < 5; j++) {
  1259.         t[j].hsize = HSIZE1;
  1260.         VSIZE1(t[j].vsize);
  1261.         t[j].refresh = REFRESH_R;
  1262.         t[j].id = STD_TIMING_ID;
  1263.         NEXT_STD_TIMING;
  1264.     }
  1265. }
  1266.  
  1267. static void
  1268. get_monitor_ranges(Uchar *c, struct monitor_ranges *r)
  1269. {
  1270.     r->min_v = MIN_V;
  1271.     r->max_v = MAX_V;
  1272.     r->min_h = MIN_H;
  1273.     r->max_h = MAX_H;
  1274.     r->max_clock = 0;
  1275.     if(MAX_CLOCK != 0xff) /* is specified? */
  1276.         r->max_clock = MAX_CLOCK * 10;
  1277.     if (HAVE_2ND_GTF) {
  1278.         r->gtf_2nd_f = F_2ND_GTF;
  1279.         r->gtf_2nd_c = C_2ND_GTF;
  1280.         r->gtf_2nd_m = M_2ND_GTF;
  1281.         r->gtf_2nd_k = K_2ND_GTF;
  1282.         r->gtf_2nd_j = J_2ND_GTF;
  1283.     } else
  1284.         r->gtf_2nd_f = 0;
  1285. }
  1286.  
  1287. static void
  1288. get_whitepoint_section(Uchar *c, struct whitePoints *wp)
  1289. {
  1290.     wp[1].white_x = WHITEX1;
  1291.     wp[1].white_y = WHITEY1;
  1292.     wp[2].white_x = WHITEX2;
  1293.     wp[2].white_y = WHITEY2;
  1294.     wp[1].index  = WHITE_INDEX1;
  1295.     wp[2].index  = WHITE_INDEX2;
  1296.     wp[1].white_gamma  = WHITE_GAMMA1;
  1297.     wp[2].white_gamma  = WHITE_GAMMA2;
  1298. }
  1299.  
  1300. static void
  1301. get_detailed_timing_section(Uchar *c, struct detailed_timings *r)
  1302. {
  1303.   r->clock = PIXEL_CLOCK;
  1304.   r->h_active = H_ACTIVE;
  1305.   r->h_blanking = H_BLANK;
  1306.   r->v_active = V_ACTIVE;
  1307.   r->v_blanking = V_BLANK;
  1308.   r->h_sync_off = H_SYNC_OFF;
  1309.   r->h_sync_width = H_SYNC_WIDTH;
  1310.   r->v_sync_off = V_SYNC_OFF;
  1311.   r->v_sync_width = V_SYNC_WIDTH;
  1312.   r->h_size = H_SIZE;
  1313.   r->v_size = V_SIZE;
  1314.   r->h_border = H_BORDER;
  1315.   r->v_border = V_BORDER;
  1316.   r->interlaced = INTERLACED;
  1317.   r->stereo = STEREO;
  1318.   r->stereo_1 = STEREO1;
  1319.   r->sync = SYNC_T;
  1320.   r->misc = MISC;
  1321. }
  1322.  
  1323.  
  1324. static Bool
  1325. validate_version(RHDPtr rhdPtr, struct edid_version *r)
  1326. {
  1327.     if (r->version != 1)
  1328.       return FALSE;
  1329.     if (r->revision > 3)
  1330.     {
  1331.       DBG(dbgprintf("EDID Version 1.%d not yet supported\n",r->revision));
  1332.       return FALSE;
  1333.     }
  1334.     return TRUE;
  1335. }
  1336.