Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2006-2007 Luc Verhaegen <lverhaegen@novell.com>.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the
  12.  * next paragraph) shall be included in all copies or substantial portions
  13.  * of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. # include <config.h>
  26. #endif
  27. #ifdef HAVE_XORG_CONFIG_H
  28. # include <xorg-config.h>
  29. #endif
  30.  
  31. #include "xf86.h"
  32. #include "rhd.h"
  33. #include "edid.h"
  34. #include "xf86DDC.h"
  35.  
  36. #include "rhd_modes.h"
  37. #include "rhd_monitor.h"
  38.  
  39. /*
  40.  * TODO:
  41.  *  - for those with access to the VESA DMT standard; review please.
  42.  *  - swap M_T_DEFAULT for M_T_EDID_...
  43.  */
  44. #define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
  45. #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
  46.  
  47. static DisplayModeRec EDIDEstablishedModes[17] = {
  48.     { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
  49.     { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
  50.     { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
  51.     { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
  52.     { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
  53.     { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
  54.     { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
  55.     { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
  56.     { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
  57.     { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
  58.     { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
  59.     { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
  60.     { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
  61.     { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
  62.     { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
  63.     { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
  64.     { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
  65. };
  66.  
  67. static DisplayModePtr
  68. EDIDModesFromEstablished(RHDPtr rhdPtr, struct established_timings *timing)
  69. {
  70.     DisplayModePtr Modes = NULL, Mode = NULL;
  71.     CARD32 bits = (timing->t1) | (timing->t2 << 8) |
  72.         ((timing->t_manu & 0x80) << 9);
  73.     int i;
  74.  
  75.     for (i = 0; i < 17; i++)
  76.         if (bits & (0x01 << i)) {
  77.             Mode = RHDModeCopy(&(EDIDEstablishedModes[i]));
  78.             Modes = RHDModesAdd(Modes, Mode);
  79.         }
  80.  
  81.     return Modes;
  82. }
  83.  
  84. /*
  85.  *
  86.  */
  87. static DisplayModePtr
  88. EDIDModesFromStandardTiming(RHDPtr rhdPtr, struct std_timings *timing)
  89. {
  90.     DisplayModePtr Modes = NULL, Mode = NULL;
  91.     int i;
  92.  
  93.     for (i = 0; i < STD_TIMINGS; i++)
  94.         if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
  95.             Mode =  RHDCVTMode(timing[i].hsize, timing[i].vsize,
  96.                                 timing[i].refresh, FALSE, FALSE);
  97.             Mode->type = M_T_DRIVER;
  98.             Modes = RHDModesAdd(Modes, Mode);
  99.         }
  100.  
  101.     return Modes;
  102. }
  103.  
  104. /*
  105.  *
  106.  */
  107. static DisplayModePtr
  108. EDIDModeFromDetailedTiming(RHDPtr rhdPtr, struct detailed_timings *timing)
  109. {
  110.     DisplayModePtr Mode;
  111.     int scrnIndex;
  112.  
  113.     /* We don't do stereo */
  114.     if (timing->stereo) {
  115.         xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We don't handle stereo.\n",
  116.                    __func__);
  117.         return NULL;
  118.     }
  119.  
  120.     /* We only do separate sync currently */
  121.     if (timing->sync != 0x03) {
  122.          xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We only handle separate"
  123.                     " sync.\n", __func__);
  124.          return NULL;
  125.     }
  126.  
  127.     Mode = xnfalloc(sizeof(DisplayModeRec));
  128.     memset(Mode, 0, sizeof(DisplayModeRec));
  129.  
  130.     Mode->name = xnfalloc(10); /* "1234x1234" */
  131.     snprintf(Mode->name, 20, "%dx%d", timing->h_active, timing->v_active);
  132.  
  133.     Mode->type = M_T_DRIVER;
  134.  
  135.     Mode->Clock = timing->clock / 1000.0;
  136.  
  137.     Mode->HDisplay = timing->h_active;
  138.     Mode->HSyncStart = timing->h_active + timing->h_sync_off;
  139.     Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
  140.     Mode->HTotal = timing->h_active + timing->h_blanking;
  141.  
  142.     Mode->VDisplay = timing->v_active;
  143.     Mode->VSyncStart = timing->v_active + timing->v_sync_off;
  144.     Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
  145.     Mode->VTotal = timing->v_active + timing->v_blanking;
  146.  
  147.     /* We ignore h/v_size and h/v_border for now. */
  148.  
  149.     if (timing->interlaced)
  150.         Mode->Flags |= V_INTERLACE;
  151.  
  152.     if (timing->misc & 0x02)
  153.         Mode->Flags |= V_PVSYNC;
  154.     else
  155.         Mode->Flags |= V_NVSYNC;
  156.  
  157.     if (timing->misc & 0x01)
  158.         Mode->Flags |= V_PHSYNC;
  159.     else
  160.         Mode->Flags |= V_NHSYNC;
  161.  
  162.     return Mode;
  163. }
  164.  
  165. /*
  166.  *
  167.  */
  168. static void
  169. EDIDGuessRangesFromModes(struct rhdMonitor *Monitor, DisplayModePtr Modes)
  170. {
  171.     DisplayModePtr Mode = Modes;
  172.  
  173.     if (!Monitor || !Modes)
  174.         return;
  175.  
  176.     for (Mode = Modes; Mode; Mode = Mode->next) {
  177.         if (!Mode->HSync)
  178.             Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
  179.  
  180.         if (!Mode->VRefresh) {
  181.             Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
  182.                 ((float) (Mode->HTotal * Mode->VTotal));
  183.             if (Mode->Flags & V_INTERLACE)
  184.                 Mode->VRefresh *= 2.0;
  185.             if (Mode->Flags & V_DBLSCAN)
  186.                 Mode->VRefresh /= 2.0;
  187.         }
  188.     }
  189.  
  190.     if (!Monitor->numHSync) {
  191.         /* set up the ranges for scanning through the modes */
  192.         Monitor->numHSync = 1;
  193.         Monitor->HSync[0].lo = 1024.0;
  194.         Monitor->HSync[0].hi = 0.0;
  195.  
  196.         for (Mode = Modes; Mode; Mode = Mode->next) {
  197.             if (Mode->HSync < Monitor->HSync[0].lo)
  198.                 Monitor->HSync[0].lo = Mode->HSync;
  199.  
  200.             if (Mode->HSync > Monitor->HSync[0].hi)
  201.                 Monitor->HSync[0].hi = Mode->HSync;
  202.         }
  203.     }
  204.  
  205.  
  206.     if (!Monitor->numVRefresh) {
  207.         Monitor->numVRefresh = 1;
  208.         Monitor->VRefresh[0].lo = 1024.0;
  209.         Monitor->VRefresh[0].hi = 0.0;
  210.  
  211.         for (Mode = Modes; Mode; Mode = Mode->next) {
  212.             if (Mode->VRefresh < Monitor->VRefresh[0].lo)
  213.                 Monitor->VRefresh[0].lo = Mode->VRefresh;
  214.  
  215.             if (Mode->VRefresh > Monitor->VRefresh[0].hi)
  216.                 Monitor->VRefresh[0].hi = Mode->VRefresh;
  217.         }
  218.     }
  219.  
  220.     if (!Monitor->Bandwidth)
  221.         for (Mode = Modes; Mode; Mode = Mode->next)
  222.             if (Mode->Clock > Monitor->Bandwidth)
  223.                 Monitor->Bandwidth = Mode->Clock;
  224. }
  225.  
  226. /*
  227.  * Determine whether this monitor does allow reduced blanking.
  228.  * Do not set it to false, to allow the user to specify this too.
  229.  */
  230. static void
  231. EDIDReducedAllowed(struct rhdMonitor *Monitor, DisplayModePtr Modes)
  232. {
  233.     DisplayModePtr Mode;
  234.  
  235.     for (Mode = Modes; Mode; Mode = Mode->next)
  236.         if (((Mode->HTotal - Mode->HDisplay) == 160) &&
  237.             ((Mode->HSyncEnd - Mode->HDisplay) == 80) &&
  238.             ((Mode->HSyncEnd - Mode->HSyncStart) == 32) &&
  239.             ((Mode->VSyncStart - Mode->VDisplay) == 3))
  240.             Monitor->ReducedAllowed = TRUE;
  241. }
  242.  
  243. /*
  244.  * Fill out rhdMonitor with xf86MonPtr information.
  245.  */
  246. void
  247. RHDMonitorEDIDSet(struct rhdMonitor *Monitor, xf86MonPtr EDID)
  248. {
  249.     DisplayModePtr Modes = NULL, Mode;
  250.     int i, preferred;
  251.  
  252.     if (!Monitor || !EDID)
  253.         return;
  254.  
  255.     /* We don't parse the detailed name yet, so use ABC-0123 */
  256.     Monitor->Name = xnfcalloc(9, 1);
  257.     snprintf(Monitor->Name, 9, "%s-%04X", EDID->vendor.name,
  258.              EDID->vendor.prod_id);
  259.  
  260.     /* Add established timings */
  261.     Mode = EDIDModesFromEstablished(Monitor->scrnIndex, &EDID->timings1);
  262.     Modes = RHDModesAdd(Modes, Mode);
  263.  
  264.     /* Add standard timings */
  265.     Mode = EDIDModesFromStandardTiming(Monitor->scrnIndex, EDID->timings2);
  266.     Modes = RHDModesAdd(Modes, Mode);
  267.  
  268.     /* First DT timing preferred? */
  269.     preferred = PREFERRED_TIMING_MODE(EDID->features.msc);
  270.  
  271.     /* Go through the detailed monitor sections */
  272.     for (i = 0; i < DET_TIMINGS; i++)
  273.         switch (EDID->det_mon[i].type) {
  274.         case DS_RANGES:
  275.             if (!Monitor->numHSync) {
  276.                 Monitor->numHSync = 1;
  277.                 Monitor->HSync[0].lo = EDID->det_mon[i].section.ranges.min_h;
  278.                 Monitor->HSync[0].hi = EDID->det_mon[i].section.ranges.max_h;
  279.             } else
  280.                 xf86DrvMsg(Monitor->scrnIndex, X_INFO,
  281.                            "\"%s\": keeping configured HSync.\n",
  282.                            Monitor->Name);
  283.  
  284.             if (!Monitor->numVRefresh) {
  285.                 Monitor->numVRefresh = 1;
  286.                 Monitor->VRefresh[0].lo = EDID->det_mon[i].section.ranges.min_v;
  287.                 Monitor->VRefresh[0].hi = EDID->det_mon[i].section.ranges.max_v;
  288.             } else
  289.                 xf86DrvMsg(Monitor->scrnIndex, X_INFO,
  290.                            "\"%s\": keeping configured VRefresh.\n",
  291.                            Monitor->Name);
  292.  
  293.             if (!Monitor->Bandwidth)
  294.                 Monitor->Bandwidth =
  295.                     EDID->det_mon[i].section.ranges.max_clock * 1000;
  296.  
  297.             break;
  298.         case DT:
  299.             Mode = EDIDModeFromDetailedTiming(Monitor->scrnIndex,
  300.                    &EDID->det_mon[i].section.d_timings);
  301.             if (Mode) {
  302.                 if (preferred) {
  303.                     Mode->type |= M_T_PREFERRED;
  304.  
  305.                     /* also grab the DPI while we are at it */
  306.                     Monitor->xDpi = (Mode->HDisplay * 25.4) /
  307.                         ((float) EDID->det_mon[i].section.d_timings.h_size) + 0.5;
  308.                     Monitor->yDpi = (Mode->VDisplay * 25.4) /
  309.                         ((float) EDID->det_mon[i].section.d_timings.v_size) + 0.5;
  310.  
  311.                     Monitor->NativeMode = Mode;
  312.                 }
  313.                 preferred = FALSE;
  314.  
  315.                 Modes = RHDModesAdd(Modes, Mode);
  316.             }
  317.             break;
  318.         case DS_STD_TIMINGS:
  319.             Mode = EDIDModesFromStandardTiming(Monitor->scrnIndex,
  320.                                                EDID->det_mon[i].section.std_t);
  321.             Modes = RHDModesAdd(Modes, Mode);
  322.             break;
  323.         case DS_NAME:
  324.             xfree(Monitor->Name);
  325.             Monitor->Name = xnfcalloc(13, 1);
  326.             memcpy(Monitor->Name, EDID->det_mon[i].section.name, 13);
  327.             break;
  328.         default:
  329.             break;
  330.         }
  331.  
  332.     if (Modes) {
  333.         EDIDGuessRangesFromModes(Monitor, Modes);
  334.         EDIDReducedAllowed(Monitor, Modes);
  335.         Monitor->Modes = RHDModesAdd(Monitor->Modes, Modes);
  336.     }
  337.  
  338.     /* Calculate DPI when we still don't have this */
  339.     if (!Monitor->xDpi || !Monitor->yDpi) {
  340.         int HDisplay = 0, VDisplay = 0;
  341.  
  342.         for (Mode = Monitor->Modes; Mode; Mode = Mode->next) {
  343.             if (Mode->HDisplay > HDisplay)
  344.                 HDisplay = Mode->HDisplay;
  345.             if (Mode->VDisplay > VDisplay)
  346.                 VDisplay = Mode->VDisplay;
  347.         }
  348.  
  349.         if (HDisplay && EDID->features.hsize)
  350.             Monitor->xDpi = (HDisplay * 2.54) / ((float) EDID->features.hsize) + 0.5;
  351.         if (VDisplay && EDID->features.vsize)
  352.             Monitor->yDpi = (VDisplay * 2.54) / ((float) EDID->features.vsize) + 0.5;
  353.  
  354.         if (!Monitor->xDpi && Monitor->yDpi)
  355.             Monitor->xDpi = Monitor->yDpi;
  356.         if (!Monitor->yDpi && Monitor->xDpi)
  357.             Monitor->yDpi = Monitor->xDpi;
  358.     }
  359. }
  360.