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(int scrnIndex, 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(int scrnIndex, 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(int scrnIndex, struct detailed_timings *timing)
  109. {
  110.     DisplayModePtr Mode;
  111.  
  112.     /* We don't do stereo */
  113.     if (timing->stereo) {
  114.         xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We don't handle stereo.\n",
  115.                    __func__);
  116.         return NULL;
  117.     }
  118.  
  119.     /* We only do separate sync currently */
  120.     if (timing->sync != 0x03) {
  121.          xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We only handle separate"
  122.                     " sync.\n", __func__);
  123.          return NULL;
  124.     }
  125.  
  126.     Mode = xnfalloc(sizeof(DisplayModeRec));
  127.     memset(Mode, 0, sizeof(DisplayModeRec));
  128.  
  129.     Mode->name = xnfalloc(10); /* "1234x1234" */
  130.     snprintf(Mode->name, 20, "%dx%d", timing->h_active, timing->v_active);
  131.  
  132.     Mode->type = M_T_DRIVER;
  133.  
  134.     Mode->Clock = timing->clock / 1000.0;
  135.  
  136.     Mode->HDisplay = timing->h_active;
  137.     Mode->HSyncStart = timing->h_active + timing->h_sync_off;
  138.     Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
  139.     Mode->HTotal = timing->h_active + timing->h_blanking;
  140.  
  141.     Mode->VDisplay = timing->v_active;
  142.     Mode->VSyncStart = timing->v_active + timing->v_sync_off;
  143.     Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
  144.     Mode->VTotal = timing->v_active + timing->v_blanking;
  145.  
  146.     /* We ignore h/v_size and h/v_border for now. */
  147.  
  148.     if (timing->interlaced)
  149.         Mode->Flags |= V_INTERLACE;
  150.  
  151.     if (timing->misc & 0x02)
  152.         Mode->Flags |= V_PVSYNC;
  153.     else
  154.         Mode->Flags |= V_NVSYNC;
  155.  
  156.     if (timing->misc & 0x01)
  157.         Mode->Flags |= V_PHSYNC;
  158.     else
  159.         Mode->Flags |= V_NHSYNC;
  160.  
  161.     return Mode;
  162. }
  163.  
  164. /*
  165.  *
  166.  */
  167. static void
  168. EDIDGuessRangesFromModes(struct rhdMonitor *Monitor, DisplayModePtr Modes)
  169. {
  170.     DisplayModePtr Mode = Modes;
  171.  
  172.     if (!Monitor || !Modes)
  173.         return;
  174.  
  175.     for (Mode = Modes; Mode; Mode = Mode->next) {
  176.         if (!Mode->HSync)
  177.             Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
  178.  
  179.         if (!Mode->VRefresh) {
  180.             Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
  181.                 ((float) (Mode->HTotal * Mode->VTotal));
  182.             if (Mode->Flags & V_INTERLACE)
  183.                 Mode->VRefresh *= 2.0;
  184.             if (Mode->Flags & V_DBLSCAN)
  185.                 Mode->VRefresh /= 2.0;
  186.         }
  187.     }
  188.  
  189.     if (!Monitor->numHSync) {
  190.         /* set up the ranges for scanning through the modes */
  191.         Monitor->numHSync = 1;
  192.         Monitor->HSync[0].lo = 1024.0;
  193.         Monitor->HSync[0].hi = 0.0;
  194.  
  195.         for (Mode = Modes; Mode; Mode = Mode->next) {
  196.             if (Mode->HSync < Monitor->HSync[0].lo)
  197.                 Monitor->HSync[0].lo = Mode->HSync;
  198.  
  199.             if (Mode->HSync > Monitor->HSync[0].hi)
  200.                 Monitor->HSync[0].hi = Mode->HSync;
  201.         }
  202.     }
  203.  
  204.  
  205.     if (!Monitor->numVRefresh) {
  206.         Monitor->numVRefresh = 1;
  207.         Monitor->VRefresh[0].lo = 1024.0;
  208.         Monitor->VRefresh[0].hi = 0.0;
  209.  
  210.         for (Mode = Modes; Mode; Mode = Mode->next) {
  211.             if (Mode->VRefresh < Monitor->VRefresh[0].lo)
  212.                 Monitor->VRefresh[0].lo = Mode->VRefresh;
  213.  
  214.             if (Mode->VRefresh > Monitor->VRefresh[0].hi)
  215.                 Monitor->VRefresh[0].hi = Mode->VRefresh;
  216.         }
  217.     }
  218.  
  219.     if (!Monitor->Bandwidth)
  220.         for (Mode = Modes; Mode; Mode = Mode->next)
  221.             if (Mode->Clock > Monitor->Bandwidth)
  222.                 Monitor->Bandwidth = Mode->Clock;
  223. }
  224.  
  225. /*
  226.  * Determine whether this monitor does allow reduced blanking.
  227.  * Do not set it to false, to allow the user to specify this too.
  228.  */
  229. static void
  230. EDIDReducedAllowed(struct rhdMonitor *Monitor, DisplayModePtr Modes)
  231. {
  232.     DisplayModePtr Mode;
  233.  
  234.     for (Mode = Modes; Mode; Mode = Mode->next)
  235.         if (((Mode->HTotal - Mode->HDisplay) == 160) &&
  236.             ((Mode->HSyncEnd - Mode->HDisplay) == 80) &&
  237.             ((Mode->HSyncEnd - Mode->HSyncStart) == 32) &&
  238.             ((Mode->VSyncStart - Mode->VDisplay) == 3))
  239.             Monitor->ReducedAllowed = TRUE;
  240. }
  241.  
  242. /*
  243.  * Fill out rhdMonitor with xf86MonPtr information.
  244.  */
  245. void
  246. RHDMonitorEDIDSet(struct rhdMonitor *Monitor, xf86MonPtr EDID)
  247. {
  248.     DisplayModePtr Modes = NULL, Mode;
  249.     int i, preferred;
  250.  
  251.     if (!Monitor || !EDID)
  252.         return;
  253.  
  254.     /* We don't parse the detailed name yet, so use ABC-0123 */
  255.     Monitor->Name = xnfcalloc(9, 1);
  256.     snprintf(Monitor->Name, 9, "%s-%04X", EDID->vendor.name,
  257.              EDID->vendor.prod_id);
  258.  
  259.     /* Add established timings */
  260.     Mode = EDIDModesFromEstablished(Monitor->scrnIndex, &EDID->timings1);
  261.     Modes = RHDModesAdd(Modes, Mode);
  262.  
  263.     /* Add standard timings */
  264.     Mode = EDIDModesFromStandardTiming(Monitor->scrnIndex, EDID->timings2);
  265.     Modes = RHDModesAdd(Modes, Mode);
  266.  
  267.     /* First DT timing preferred? */
  268.     preferred = PREFERRED_TIMING_MODE(EDID->features.msc);
  269.  
  270.     /* Go through the detailed monitor sections */
  271.     for (i = 0; i < DET_TIMINGS; i++)
  272.         switch (EDID->det_mon[i].type) {
  273.         case DS_RANGES:
  274.             if (!Monitor->numHSync) {
  275.                 Monitor->numHSync = 1;
  276.                 Monitor->HSync[0].lo = EDID->det_mon[i].section.ranges.min_h;
  277.                 Monitor->HSync[0].hi = EDID->det_mon[i].section.ranges.max_h;
  278.             } else
  279.                 xf86DrvMsg(Monitor->scrnIndex, X_INFO,
  280.                            "\"%s\": keeping configured HSync.\n",
  281.                            Monitor->Name);
  282.  
  283.             if (!Monitor->numVRefresh) {
  284.                 Monitor->numVRefresh = 1;
  285.                 Monitor->VRefresh[0].lo = EDID->det_mon[i].section.ranges.min_v;
  286.                 Monitor->VRefresh[0].hi = EDID->det_mon[i].section.ranges.max_v;
  287.             } else
  288.                 xf86DrvMsg(Monitor->scrnIndex, X_INFO,
  289.                            "\"%s\": keeping configured VRefresh.\n",
  290.                            Monitor->Name);
  291.  
  292.             if (!Monitor->Bandwidth)
  293.                 Monitor->Bandwidth =
  294.                     EDID->det_mon[i].section.ranges.max_clock * 1000;
  295.  
  296.             break;
  297.         case DT:
  298.             Mode = EDIDModeFromDetailedTiming(Monitor->scrnIndex,
  299.                    &EDID->det_mon[i].section.d_timings);
  300.             if (Mode) {
  301.                 if (preferred) {
  302.                     Mode->type |= M_T_PREFERRED;
  303.  
  304.                     /* also grab the DPI while we are at it */
  305.                     Monitor->xDpi = (Mode->HDisplay * 25.4) /
  306.                         ((float) EDID->det_mon[i].section.d_timings.h_size) + 0.5;
  307.                     Monitor->yDpi = (Mode->VDisplay * 25.4) /
  308.                         ((float) EDID->det_mon[i].section.d_timings.v_size) + 0.5;
  309.  
  310.                     Monitor->NativeMode = Mode;
  311.                 }
  312.                 preferred = FALSE;
  313.  
  314.                 Modes = RHDModesAdd(Modes, Mode);
  315.             }
  316.             break;
  317.         case DS_STD_TIMINGS:
  318.             Mode = EDIDModesFromStandardTiming(Monitor->scrnIndex,
  319.                                                EDID->det_mon[i].section.std_t);
  320.             Modes = RHDModesAdd(Modes, Mode);
  321.             break;
  322.         case DS_NAME:
  323.             xfree(Monitor->Name);
  324.             Monitor->Name = xnfcalloc(13, 1);
  325.             memcpy(Monitor->Name, EDID->det_mon[i].section.name, 13);
  326.             break;
  327.         default:
  328.             break;
  329.         }
  330.  
  331.     if (Modes) {
  332.         EDIDGuessRangesFromModes(Monitor, Modes);
  333.         EDIDReducedAllowed(Monitor, Modes);
  334.         Monitor->Modes = RHDModesAdd(Monitor->Modes, Modes);
  335.     }
  336.  
  337.     /* Calculate DPI when we still don't have this */
  338.     if (!Monitor->xDpi || !Monitor->yDpi) {
  339.         int HDisplay = 0, VDisplay = 0;
  340.  
  341.         for (Mode = Monitor->Modes; Mode; Mode = Mode->next) {
  342.             if (Mode->HDisplay > HDisplay)
  343.                 HDisplay = Mode->HDisplay;
  344.             if (Mode->VDisplay > VDisplay)
  345.                 VDisplay = Mode->VDisplay;
  346.         }
  347.  
  348.         if (HDisplay && EDID->features.hsize)
  349.             Monitor->xDpi = (HDisplay * 2.54) / ((float) EDID->features.hsize) + 0.5;
  350.         if (VDisplay && EDID->features.vsize)
  351.             Monitor->yDpi = (VDisplay * 2.54) / ((float) EDID->features.vsize) + 0.5;
  352.  
  353.         if (!Monitor->xDpi && Monitor->yDpi)
  354.             Monitor->xDpi = Monitor->yDpi;
  355.         if (!Monitor->yDpi && Monitor->xDpi)
  356.             Monitor->yDpi = Monitor->xDpi;
  357.     }
  358. }
  359.