~ubuntu-branches/ubuntu/oneiric/xserver-xorg-video-ati/oneiric

« back to all changes in this revision

Viewing changes to src/modes/xf86EdidModes.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker
  • Date: 2010-07-08 16:45:59 UTC
  • mfrom: (1.1.34 upstream) (0.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100708164559-t1gwcpobj4n39lhf
Tags: 1:6.13.1-1ubuntu1
* Merge from Debian Unstable. Remainning Ubuntu changes:
  + debian/control:
    - Add quilt to build-depends for Ubuntu patches
  + debian/patches/100_radeon-6.9.0-bgnr-enable.patch:
    - Smooth plymouth transition enablement patch
  + debian/rules:
    - Add xsfbs patchsys
    - Drop /etc/modprobe.d/radeon-kms.conf install.
  + debian/xserver-xorg-video-ati.{pre,post}inst.in:
    - Clean existing /etc/modprobe.d/radeon-kms.conf on install.
      At best this does nothing (KMS is the default for our kernel)
      and at worst it makes it harder to disable KMS.
* Add debian/gbp.conf pointing to Ubuntu branch to make git-buildpackage
  less narky.
* Drop 102-no-xv-rn50.patch and 103_new_pci_ids.patch from previous
  Ubuntu releases, they are upstream now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
#include <string.h>
46
46
#include <math.h>
47
47
 
 
48
static void handle_detailed_rblank(struct detailed_monitor_section *det_mon,
 
49
                                   void *data)
 
50
{
 
51
    if (det_mon->type == DS_RANGES)
 
52
        if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
 
53
            *(Bool*)data = TRUE;
 
54
}
 
55
 
48
56
static Bool
49
57
xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
50
58
{
51
59
    /* EDID 1.4 explicitly defines RB support */
52
60
    if (DDC->ver.revision >= 4) {
53
 
        int i;
54
 
        for (i = 0; i < DET_TIMINGS; i++) {
55
 
            struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
56
 
            if (det_mon->type == DS_RANGES)
57
 
                if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
58
 
                    return TRUE;
59
 
        }
60
 
        
61
 
        return FALSE;
 
61
        Bool ret = FALSE;
 
62
 
 
63
        xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret);
 
64
        return ret;
62
65
    }
63
66
 
64
67
    /* For anything older, assume digital means RB support. Boo. */
68
71
    return FALSE;
69
72
}
70
73
 
71
 
/*
72
 
 * Quirks to work around broken EDID data from various monitors.
73
 
 */
74
 
 
75
 
typedef enum {
76
 
    DDC_QUIRK_NONE = 0,
77
 
    /* First detailed mode is bogus, prefer largest mode at 60hz */
78
 
    DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
79
 
    /* 135MHz clock is too high, drop a bit */
80
 
    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
81
 
    /* Prefer the largest mode at 75 Hz */
82
 
    DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
83
 
    /* Convert detailed timing's horizontal from units of cm to mm */
84
 
    DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
85
 
    /* Convert detailed timing's vertical from units of cm to mm */
86
 
    DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
87
 
    /* Detailed timing descriptors have bogus size values, so just take the
88
 
     * maximum size and use that.
89
 
     */
90
 
    DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
91
 
    /* Monitor forgot to set the first detailed is preferred bit. */
92
 
    DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
93
 
    /* use +hsync +vsync for detailed mode */
94
 
    DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
95
 
    /* Force single-link DVI bandwidth limit */
96
 
    DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
97
 
} ddc_quirk_t;
98
 
 
99
74
static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
100
75
{
101
76
    /* Belinea 10 15 55 */
160
135
        DDC->vendor.prod_id == 47360)
161
136
        return TRUE;
162
137
 
 
138
    /* Bug #10304: LGPhilipsLCD LP154W01-A5 */
 
139
    if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
 
140
        DDC->vendor.prod_id == 0)
 
141
        return TRUE;
 
142
 
 
143
    /* Bug #24482: LGPhilipsLCD LP154W01-TLA1 */
 
144
    if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
 
145
        DDC->vendor.prod_id == 0x2a00)
 
146
        return TRUE;
 
147
 
163
148
    /* Bug #21750: Samsung Syncmaster 2333HD */
164
149
    if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
165
150
        DDC->vendor.prod_id == 1157)
170
155
 
171
156
static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC)
172
157
{
173
 
    /* Bug #10304: LGPhilipsLCD LP154W01-A5 */
174
 
    if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
175
 
        (DDC->vendor.prod_id == 0 || DDC->vendor.prod_id == 0x2a00))
176
 
        return TRUE;
177
 
 
178
158
    /* Bug #21324: Iiyama Vision Master 450 */
179
159
    if (memcmp (DDC->vendor.name, "IVM", 4) == 0 &&
180
160
        DDC->vendor.prod_id == 6400)
266
246
    },
267
247
    {
268
248
        quirk_detailed_use_maximum_size,   DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
269
 
        "Detailed timings give sizes in cm."
 
249
        "Use maximum size instead of detailed timing sizes."
270
250
    },
271
251
    {
272
252
        quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED,
338
318
}
339
319
 
340
320
/* Autogenerated from the DMT spec */
341
 
static const DisplayModeRec DMTModes[] = {
 
321
const DisplayModeRec DMTModes[] = {
342
322
    { MODEPREFIX,    31500,  640,  672,  736,  832, 0,  350,  382,  385,  445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */
343
323
    { MODEPREFIX,    31500,  640,  672,  736,  832, 0,  400,  401,  404,  445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */
344
324
    { MODEPREFIX,    35500,  720,  756,  828,  936, 0,  400,  401,  404,  446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */
448
428
 * part of the DMT pool.  For the 'standard' EDID mode descriptor there's
449
429
 * no way to specify whether the mode should be RB or not.
450
430
 */
451
 
static DisplayModePtr
 
431
DisplayModePtr
452
432
FindDMTMode(int hsize, int vsize, int refresh, Bool rb)
453
433
{
454
434
    int i;
498
478
        vsize = timing[i].vsize;
499
479
        refresh = timing[i].refresh;
500
480
 
501
 
        /* HDTV hack.  Hooray. */
502
 
        if (hsize == 1360 && vsize == 765 && refresh == 60) {
 
481
        /* HDTV hack, because you can't say 1366 */
 
482
        if (refresh == 60 &&
 
483
            ((hsize == 1360 && vsize == 765) ||
 
484
             (hsize == 1368 && vsize == 769))) {
503
485
            Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE);
504
486
            Mode->HDisplay = 1366;
505
487
            Mode->VSyncStart--;
527
509
    return Modes;
528
510
}
529
511
 
 
512
static void
 
513
DDCModeDoInterlaceQuirks(DisplayModePtr mode)
 
514
{
 
515
    /*
 
516
     * EDID is delightfully ambiguous about how interlaced modes are to be
 
517
     * encoded.  X's internal representation is of frame height, but some
 
518
     * HDTV detailed timings are encoded as field height.
 
519
     *
 
520
     * The format list here is from CEA, in frame size.  Technically we
 
521
     * should be checking refresh rate too.  Whatever.
 
522
     */
 
523
    static const struct {
 
524
        int w, h;
 
525
    } cea_interlaced[] = {
 
526
        { 1920, 1080 },
 
527
        {  720,  480 },
 
528
        { 1440,  480 },
 
529
        { 2880,  480 },
 
530
        {  720,  576 },
 
531
        { 1440,  576 },
 
532
        { 2880,  576 },
 
533
    };
 
534
    static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
 
535
    int i;
 
536
 
 
537
    for (i = 0; i < n_modes; i++) {
 
538
        if ((mode->HDisplay == cea_interlaced[i].w) &&
 
539
            (mode->VDisplay == cea_interlaced[i].h / 2)) {
 
540
            mode->VDisplay *= 2;
 
541
            mode->VSyncStart *= 2;
 
542
            mode->VSyncEnd *= 2;
 
543
            mode->VTotal *= 2;
 
544
            mode->VTotal |= 1;
 
545
        }
 
546
    }
 
547
 
 
548
    mode->Flags |= V_INTERLACE;
 
549
}
 
550
 
530
551
/*
531
552
 *
532
553
 */
587
608
 
588
609
    /* perform basic check on the detail timing */
589
610
    if (Mode->HSyncEnd > Mode->HTotal || Mode->VSyncEnd > Mode->VTotal) {
590
 
        xfree(Mode);
 
611
        free(Mode);
591
612
        return NULL;
592
613
    }
593
614
 
594
 
    xf86SetModeDefaultName(Mode);
595
 
 
596
615
    /* We ignore h/v_size and h/v_border for now. */
597
616
 
598
617
    if (timing->interlaced)
599
 
        Mode->Flags |= V_INTERLACE;
 
618
        DDCModeDoInterlaceQuirks(Mode);
600
619
 
601
620
    if (quirks & DDC_QUIRK_DETAILED_SYNC_PP)
602
621
        Mode->Flags |= V_PVSYNC | V_PHSYNC;
612
631
            Mode->Flags |= V_NHSYNC;
613
632
    }
614
633
 
 
634
    xf86SetModeDefaultName(Mode);
 
635
 
615
636
    return Mode;
616
637
}
617
638
 
774
795
    }
775
796
}
776
797
 
777
 
static ddc_quirk_t
 
798
ddc_quirk_t
778
799
xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
779
800
{
780
801
    ddc_quirk_t quirks;
794
815
    return quirks;
795
816
}
796
817
 
 
818
void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
 
819
                              ddc_quirk_t quirks,
 
820
                              int hsize, int vsize)
 
821
{
 
822
    if (det_mon->type != DT)
 
823
        return;
 
824
 
 
825
    if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
 
826
        det_mon->section.d_timings.h_size *= 10;
 
827
 
 
828
    if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
 
829
        det_mon->section.d_timings.v_size *= 10;
 
830
 
 
831
    if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
 
832
        det_mon->section.d_timings.h_size = 10 * hsize;
 
833
        det_mon->section.d_timings.v_size = 10 * vsize;
 
834
    }
 
835
}
 
836
 
797
837
/**
798
838
 * Applies monitor-specific quirks to the decoded EDID information.
799
839
 *
807
847
    int i;
808
848
 
809
849
    for (i = 0; i < DET_TIMINGS; i++) {
810
 
        struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
811
 
 
812
 
        if (det_mon->type != DT)
813
 
            continue;
814
 
 
815
 
        if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
816
 
            det_mon->section.d_timings.h_size *= 10;
817
 
 
818
 
        if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
819
 
            det_mon->section.d_timings.v_size *= 10;
820
 
 
821
 
        if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
822
 
            det_mon->section.d_timings.h_size = 10 * DDC->features.hsize;
823
 
            det_mon->section.d_timings.v_size = 10 * DDC->features.vsize;
824
 
        }
 
850
        xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks,
 
851
                                 DDC->features.hsize,
 
852
                                 DDC->features.vsize);
825
853
    }
826
854
}
827
855
 
866
894
            best->type |= M_T_PREFERRED;
867
895
}
868
896
 
 
897
#define CEA_VIDEO_MODES_NUM  64
 
898
static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = {
 
899
    { MODEPREFIX,    25175,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */
 
900
    { MODEPREFIX,    27000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */
 
901
    { MODEPREFIX,    27000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */
 
902
    { MODEPREFIX,    74250, 1280, 1390, 1430, 1650, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */
 
903
    { MODEPREFIX,    74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */
 
904
    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */
 
905
    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */
 
906
    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */
 
907
    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */
 
908
    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */
 
909
    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */
 
910
    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */
 
911
    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */
 
912
    { MODEPREFIX,    54000, 1440, 1472, 1596, 1716, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */
 
913
    { MODEPREFIX,    54000, 1440, 1472, 1596, 1716, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */
 
914
    { MODEPREFIX,   148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */
 
915
    { MODEPREFIX,    27000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */
 
916
    { MODEPREFIX,    27000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */
 
917
    { MODEPREFIX,    74250, 1280, 1720, 1760, 1980, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */
 
918
    { MODEPREFIX,    74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */
 
919
    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */
 
920
    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */
 
921
    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */
 
922
    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */
 
923
    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */
 
924
    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */
 
925
    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */
 
926
    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */
 
927
    { MODEPREFIX,    54000, 1440, 1464, 1592, 1728, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */
 
928
    { MODEPREFIX,    54000, 1440, 1464, 1592, 1728, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */
 
929
    { MODEPREFIX,   148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */
 
930
    { MODEPREFIX,    74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */
 
931
    { MODEPREFIX,    74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */
 
932
    { MODEPREFIX,    74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */
 
933
    { MODEPREFIX,   108000, 2880, 2944, 3192, 3432, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */
 
934
    { MODEPREFIX,   108000, 2880, 2944, 3192, 3432, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */
 
935
    { MODEPREFIX,   108000, 2880, 2928, 3184, 3456, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */
 
936
    { MODEPREFIX,   108000, 2880, 2928, 3184, 3456, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */
 
937
    { MODEPREFIX,    72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */
 
938
    { MODEPREFIX,   148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */
 
939
    { MODEPREFIX,   148500, 1280, 1720, 1760, 1980, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */
 
940
    { MODEPREFIX,    54000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */
 
941
    { MODEPREFIX,    54000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */
 
942
    { MODEPREFIX,    54000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */
 
943
    { MODEPREFIX,    54000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */
 
944
    { MODEPREFIX,   148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */
 
945
    { MODEPREFIX,   148500, 1280, 1390, 1430, 1650, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */
 
946
    { MODEPREFIX,    54000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */
 
947
    { MODEPREFIX,    54000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */
 
948
    { MODEPREFIX,    54000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */
 
949
    { MODEPREFIX,    54000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */
 
950
    { MODEPREFIX,   108000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */
 
951
    { MODEPREFIX,   108000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */
 
952
    { MODEPREFIX,   108000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */
 
953
    { MODEPREFIX,   108000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */
 
954
    { MODEPREFIX,   108000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */
 
955
    { MODEPREFIX,   108000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */
 
956
    { MODEPREFIX,   108000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */
 
957
    { MODEPREFIX,   108000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */
 
958
    { MODEPREFIX,    59400, 1280, 3040, 3080, 3300, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */
 
959
    { MODEPREFIX,    74250, 3700, 3740, 1430, 3960, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */
 
960
    { MODEPREFIX,    74250, 1280, 3040, 3080, 3300, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */
 
961
    { MODEPREFIX,   297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */
 
962
    { MODEPREFIX,   297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */
 
963
};
 
964
 
 
965
/* chose mode line by cea short video descriptor*/
 
966
static void handle_cea_svd(struct cea_video_block *video, void *data)
 
967
{
 
968
    DisplayModePtr Mode;
 
969
    DisplayModePtr *Modes = (DisplayModePtr *) data;
 
970
    int vid;
 
971
 
 
972
    vid = video ->video_code & 0x7f;
 
973
    if (vid < CEA_VIDEO_MODES_NUM) {
 
974
        Mode = xf86DuplicateMode(CEAVideoModes + vid);
 
975
        *Modes = xf86ModesAdd(*Modes, Mode);
 
976
    }
 
977
}
 
978
 
 
979
static DisplayModePtr
 
980
DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr)
 
981
{
 
982
    DisplayModePtr Modes = NULL;
 
983
 
 
984
    xf86ForEachVideoBlock(MonPtr,
 
985
                          handle_cea_svd,
 
986
                          &Modes);
 
987
 
 
988
    return Modes;
 
989
}
 
990
 
 
991
struct det_modes_parameter {
 
992
    xf86MonPtr DDC;
 
993
    ddc_quirk_t quirks;
 
994
    DisplayModePtr  Modes;
 
995
    Bool rb;
 
996
    Bool preferred;
 
997
    int timing_level;
 
998
};
 
999
 
 
1000
static void handle_detailed_modes(struct detailed_monitor_section *det_mon,
 
1001
                                  void *data)
 
1002
{
 
1003
    DisplayModePtr  Mode;
 
1004
    struct det_modes_parameter *p = (struct det_modes_parameter *)data;
 
1005
 
 
1006
    xf86DetTimingApplyQuirks(det_mon,p->quirks,
 
1007
                             p->DDC->features.hsize,
 
1008
                             p->DDC->features.vsize);
 
1009
 
 
1010
    switch (det_mon->type) {
 
1011
    case DT:
 
1012
        Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex,
 
1013
                                         &det_mon->section.d_timings,
 
1014
                                         p->preferred,
 
1015
                                         p->quirks);
 
1016
        p->preferred = FALSE;
 
1017
        p->Modes = xf86ModesAdd(p->Modes, Mode);
 
1018
        break;
 
1019
    case DS_STD_TIMINGS:
 
1020
        Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
 
1021
                                          p->quirks, p->timing_level,p->rb);
 
1022
        p->Modes = xf86ModesAdd(p->Modes, Mode);
 
1023
        break;
 
1024
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
 
1025
    case DS_CVT:
 
1026
        Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt);
 
1027
        p->Modes = xf86ModesAdd(p->Modes, Mode);
 
1028
        break;
 
1029
#endif
 
1030
    case DS_EST_III:
 
1031
        Mode = DDCModesFromEstIII(det_mon->section.est_iii);
 
1032
        p->Modes = xf86ModesAdd(p->Modes, Mode);
 
1033
        break;
 
1034
    default:
 
1035
        break;
 
1036
    }
 
1037
}
 
1038
 
869
1039
DisplayModePtr
870
1040
xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
871
1041
{
872
 
    int             i;
873
1042
    DisplayModePtr  Modes = NULL, Mode;
874
1043
    ddc_quirk_t     quirks;
875
1044
    Bool            preferred, rb;
876
1045
    int             timing_level;
 
1046
    struct det_modes_parameter p;
877
1047
 
878
1048
    xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
879
1049
                DDC->vendor.name, DDC->vendor.prod_id);
892
1062
 
893
1063
    timing_level = MonitorStandardTimingLevel(DDC);
894
1064
 
895
 
    for (i = 0; i < DET_TIMINGS; i++) {
896
 
        struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
897
 
 
898
 
        Mode = NULL;
899
 
        switch (det_mon->type) {
900
 
        case DT:
901
 
            Mode = DDCModeFromDetailedTiming(scrnIndex,
902
 
                                             &det_mon->section.d_timings,
903
 
                                             preferred,
904
 
                                             quirks);
905
 
            preferred = FALSE;
906
 
            break;
907
 
        case DS_STD_TIMINGS:
908
 
            Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
909
 
                                              quirks, timing_level, rb);
910
 
            break;
911
 
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
912
 
        case DS_CVT:
913
 
            Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt);
914
 
            break;
915
 
#endif
916
 
        case DS_EST_III:
917
 
            Mode = DDCModesFromEstIII(det_mon->section.est_iii);
918
 
            break;
919
 
        default:
920
 
            break;
921
 
        }
922
 
        Modes = xf86ModesAdd(Modes, Mode);
923
 
    }
 
1065
    p.quirks = quirks;
 
1066
    p.DDC = DDC;
 
1067
    p.Modes = Modes;
 
1068
    p.rb = rb;
 
1069
    p.preferred = preferred;
 
1070
    p.timing_level = timing_level;
 
1071
    xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p);
 
1072
    Modes = p.Modes;
924
1073
 
925
1074
    /* Add established timings */
926
1075
    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
930
1079
    Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
931
1080
    Modes = xf86ModesAdd(Modes, Mode);
932
1081
 
 
1082
    /* Add cea-extension mode timings */
 
1083
    Mode = DDCModesFromCEAExtension(scrnIndex,DDC);
 
1084
    Modes = xf86ModesAdd(Modes, Mode);
 
1085
 
933
1086
    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
934
1087
        xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
935
1088
 
936
1089
    if (quirks & DDC_QUIRK_PREFER_LARGE_75)
937
1090
        xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
938
1091
 
 
1092
    Modes = xf86PruneDuplicateModes(Modes);
 
1093
 
939
1094
    return Modes;
940
1095
}
941
1096
 
 
1097
struct det_mon_parameter {
 
1098
    MonPtr Monitor;
 
1099
    ddc_quirk_t quirks;
 
1100
    Bool have_hsync;
 
1101
    Bool have_vrefresh;
 
1102
    Bool have_maxpixclock;
 
1103
};
 
1104
 
 
1105
static void handle_detailed_monset(struct detailed_monitor_section *det_mon,
 
1106
                                   void *data)
 
1107
{
 
1108
    int clock;
 
1109
    struct det_mon_parameter *p = (struct det_mon_parameter *)data;
 
1110
    int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex;
 
1111
 
 
1112
    switch (det_mon->type) {
 
1113
    case DS_RANGES:
 
1114
        if (!p->have_hsync) {
 
1115
            if (!p->Monitor->nHsync)
 
1116
                xf86DrvMsg(scrnIndex, X_INFO,
 
1117
                    "Using EDID range info for horizontal sync\n");
 
1118
                p->Monitor->hsync[p->Monitor->nHsync].lo =
 
1119
                    det_mon->section.ranges.min_h;
 
1120
                p->Monitor->hsync[p->Monitor->nHsync].hi =
 
1121
                    det_mon->section.ranges.max_h;
 
1122
                p->Monitor->nHsync++;
 
1123
        } else {
 
1124
            xf86DrvMsg(scrnIndex, X_INFO,
 
1125
                "Using hsync ranges from config file\n");
 
1126
        }
 
1127
 
 
1128
        if (!p->have_vrefresh) {
 
1129
            if (!p->Monitor->nVrefresh)
 
1130
                xf86DrvMsg(scrnIndex, X_INFO,
 
1131
                    "Using EDID range info for vertical refresh\n");
 
1132
            p->Monitor->vrefresh[p->Monitor->nVrefresh].lo =
 
1133
                det_mon->section.ranges.min_v;
 
1134
            p->Monitor->vrefresh[p->Monitor->nVrefresh].hi =
 
1135
                det_mon->section.ranges.max_v;
 
1136
            p->Monitor->nVrefresh++;
 
1137
        } else {
 
1138
            xf86DrvMsg(scrnIndex, X_INFO,
 
1139
                "Using vrefresh ranges from config file\n");
 
1140
        }
 
1141
 
 
1142
        clock = det_mon->section.ranges.max_clock * 1000;
 
1143
        if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK)
 
1144
            clock = min(clock, 165000);
 
1145
        if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock)
 
1146
            p->Monitor->maxPixClock = clock;
 
1147
 
 
1148
        break;
 
1149
    default:
 
1150
        break;
 
1151
    }
 
1152
}
 
1153
 
942
1154
/*
943
1155
 * Fill out MonPtr with xf86MonPtr information.
944
1156
 */
945
1157
void
946
 
xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 
1158
xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
947
1159
{
948
1160
    DisplayModePtr Modes = NULL, Mode;
949
 
    int i, clock;
950
 
    Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE;
951
 
    ddc_quirk_t quirks;
 
1161
    struct det_mon_parameter p;
952
1162
 
953
1163
    if (!Monitor || !DDC)
954
1164
        return;
955
1165
 
956
1166
    Monitor->DDC = DDC;
957
1167
 
958
 
    quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE);
959
 
 
960
 
    if (Monitor->widthmm <= 0 && Monitor->heightmm <= 0) {
 
1168
    if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) {
961
1169
        Monitor->widthmm = 10 * DDC->features.hsize;
962
1170
        Monitor->heightmm = 10 * DDC->features.vsize;
963
1171
    }
966
1174
 
967
1175
    Modes = xf86DDCGetModes(scrnIndex, DDC);
968
1176
 
969
 
    /* Skip EDID ranges if they were specified in the config file */
970
 
    have_hsync = (Monitor->nHsync != 0);
971
 
    have_vrefresh = (Monitor->nVrefresh != 0);
972
 
    have_maxpixclock = (Monitor->maxPixClock != 0);
973
 
 
974
1177
    /* Go through the detailed monitor sections */
975
 
    for (i = 0; i < DET_TIMINGS; i++) {
976
 
        switch (DDC->det_mon[i].type) {
977
 
        case DS_RANGES:
978
 
            if (!have_hsync) {
979
 
                if (!Monitor->nHsync)
980
 
                    xf86DrvMsg(scrnIndex, X_INFO,
981
 
                            "Using EDID range info for horizontal sync\n");
982
 
                Monitor->hsync[Monitor->nHsync].lo =
983
 
                    DDC->det_mon[i].section.ranges.min_h;
984
 
                Monitor->hsync[Monitor->nHsync].hi =
985
 
                    DDC->det_mon[i].section.ranges.max_h;
986
 
                Monitor->nHsync++;
987
 
            } else {
988
 
                xf86DrvMsg(scrnIndex, X_INFO,
989
 
                        "Using hsync ranges from config file\n");
990
 
            }
991
 
 
992
 
            if (!have_vrefresh) {
993
 
                if (!Monitor->nVrefresh)
994
 
                    xf86DrvMsg(scrnIndex, X_INFO,
995
 
                            "Using EDID range info for vertical refresh\n");
996
 
                Monitor->vrefresh[Monitor->nVrefresh].lo =
997
 
                    DDC->det_mon[i].section.ranges.min_v;
998
 
                Monitor->vrefresh[Monitor->nVrefresh].hi =
999
 
                    DDC->det_mon[i].section.ranges.max_v;
1000
 
                Monitor->nVrefresh++;
1001
 
            } else {
1002
 
                xf86DrvMsg(scrnIndex, X_INFO,
1003
 
                        "Using vrefresh ranges from config file\n");
1004
 
            }
1005
 
 
1006
 
            clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
1007
 
            if (quirks & DDC_QUIRK_DVI_SINGLE_LINK)
1008
 
                clock = min(clock, 165000);
1009
 
            if (!have_maxpixclock && clock > Monitor->maxPixClock)
1010
 
                Monitor->maxPixClock = clock;
1011
 
 
1012
 
            break;
1013
 
        default:
1014
 
            break;
1015
 
        }
1016
 
    }
 
1178
    p.Monitor = Monitor;
 
1179
    p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE);
 
1180
    p.have_hsync = (Monitor->nHsync != 0);
 
1181
    p.have_vrefresh = (Monitor->nVrefresh != 0);
 
1182
    p.have_maxpixclock = (Monitor->maxPixClock != 0);
 
1183
    xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p);
1017
1184
 
1018
1185
    if (Modes) {
1019
1186
        /* Print Modes */