diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/drm_edid.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 422 |
1 files changed, 271 insertions, 151 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b54ba63d506e..18f41d7061f0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * DEALINGS IN THE SOFTWARE. | 27 | * DEALINGS IN THE SOFTWARE. |
28 | */ | 28 | */ |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
31 | #include <linux/i2c-algo-bit.h> | 32 | #include <linux/i2c-algo-bit.h> |
32 | #include "drmP.h" | 33 | #include "drmP.h" |
@@ -60,8 +61,7 @@ | |||
60 | #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) | 61 | #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) |
61 | /* use +hsync +vsync for detailed mode */ | 62 | /* use +hsync +vsync for detailed mode */ |
62 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) | 63 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
63 | /* define the number of Extension EDID block */ | 64 | |
64 | #define MAX_EDID_EXT_NUM 4 | ||
65 | 65 | ||
66 | #define LEVEL_DMT 0 | 66 | #define LEVEL_DMT 0 |
67 | #define LEVEL_GTF 1 | 67 | #define LEVEL_GTF 1 |
@@ -85,6 +85,8 @@ static struct edid_quirk { | |||
85 | 85 | ||
86 | /* Envision Peripherals, Inc. EN-7100e */ | 86 | /* Envision Peripherals, Inc. EN-7100e */ |
87 | { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, | 87 | { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, |
88 | /* Envision EN2028 */ | ||
89 | { "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 }, | ||
88 | 90 | ||
89 | /* Funai Electronics PM36B */ | 91 | /* Funai Electronics PM36B */ |
90 | { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | | 92 | { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | |
@@ -114,27 +116,29 @@ static const u8 edid_header[] = { | |||
114 | }; | 116 | }; |
115 | 117 | ||
116 | /** | 118 | /** |
117 | * edid_is_valid - sanity check EDID data | 119 | * drm_edid_is_valid - sanity check EDID data |
118 | * @edid: EDID data | 120 | * @edid: EDID data |
119 | * | 121 | * |
120 | * Sanity check the EDID block by looking at the header, the version number | 122 | * Sanity check the EDID block by looking at the header, the version number |
121 | * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's | 123 | * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's |
122 | * valid. | 124 | * valid. |
123 | */ | 125 | */ |
124 | static bool edid_is_valid(struct edid *edid) | 126 | bool drm_edid_is_valid(struct edid *edid) |
125 | { | 127 | { |
126 | int i; | 128 | int i, score = 0; |
127 | u8 csum = 0; | 129 | u8 csum = 0; |
128 | u8 *raw_edid = (u8 *)edid; | 130 | u8 *raw_edid = (u8 *)edid; |
129 | 131 | ||
130 | if (memcmp(edid->header, edid_header, sizeof(edid_header))) | 132 | for (i = 0; i < sizeof(edid_header); i++) |
131 | goto bad; | 133 | if (raw_edid[i] == edid_header[i]) |
132 | if (edid->version != 1) { | 134 | score++; |
133 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); | 135 | |
136 | if (score == 8) ; | ||
137 | else if (score >= 6) { | ||
138 | DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); | ||
139 | memcpy(raw_edid, edid_header, sizeof(edid_header)); | ||
140 | } else | ||
134 | goto bad; | 141 | goto bad; |
135 | } | ||
136 | if (edid->revision > 4) | ||
137 | DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); | ||
138 | 142 | ||
139 | for (i = 0; i < EDID_LENGTH; i++) | 143 | for (i = 0; i < EDID_LENGTH; i++) |
140 | csum += raw_edid[i]; | 144 | csum += raw_edid[i]; |
@@ -143,6 +147,14 @@ static bool edid_is_valid(struct edid *edid) | |||
143 | goto bad; | 147 | goto bad; |
144 | } | 148 | } |
145 | 149 | ||
150 | if (edid->version != 1) { | ||
151 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); | ||
152 | goto bad; | ||
153 | } | ||
154 | |||
155 | if (edid->revision > 4) | ||
156 | DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); | ||
157 | |||
146 | return 1; | 158 | return 1; |
147 | 159 | ||
148 | bad: | 160 | bad: |
@@ -153,6 +165,7 @@ bad: | |||
153 | } | 165 | } |
154 | return 0; | 166 | return 0; |
155 | } | 167 | } |
168 | EXPORT_SYMBOL(drm_edid_is_valid); | ||
156 | 169 | ||
157 | /** | 170 | /** |
158 | * edid_vendor - match a string against EDID's obfuscated vendor field | 171 | * edid_vendor - match a string against EDID's obfuscated vendor field |
@@ -481,16 +494,17 @@ static struct drm_display_mode drm_dmt_modes[] = { | |||
481 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | 494 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, |
482 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | 495 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
483 | }; | 496 | }; |
497 | static const int drm_num_dmt_modes = | ||
498 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
484 | 499 | ||
485 | static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, | 500 | static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, |
486 | int hsize, int vsize, int fresh) | 501 | int hsize, int vsize, int fresh) |
487 | { | 502 | { |
488 | int i, count; | 503 | int i; |
489 | struct drm_display_mode *ptr, *mode; | 504 | struct drm_display_mode *ptr, *mode; |
490 | 505 | ||
491 | count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
492 | mode = NULL; | 506 | mode = NULL; |
493 | for (i = 0; i < count; i++) { | 507 | for (i = 0; i < drm_num_dmt_modes; i++) { |
494 | ptr = &drm_dmt_modes[i]; | 508 | ptr = &drm_dmt_modes[i]; |
495 | if (hsize == ptr->hdisplay && | 509 | if (hsize == ptr->hdisplay && |
496 | vsize == ptr->vdisplay && | 510 | vsize == ptr->vdisplay && |
@@ -587,6 +601,50 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, | |||
587 | return mode; | 601 | return mode; |
588 | } | 602 | } |
589 | 603 | ||
604 | /* | ||
605 | * EDID is delightfully ambiguous about how interlaced modes are to be | ||
606 | * encoded. Our internal representation is of frame height, but some | ||
607 | * HDTV detailed timings are encoded as field height. | ||
608 | * | ||
609 | * The format list here is from CEA, in frame size. Technically we | ||
610 | * should be checking refresh rate too. Whatever. | ||
611 | */ | ||
612 | static void | ||
613 | drm_mode_do_interlace_quirk(struct drm_display_mode *mode, | ||
614 | struct detailed_pixel_timing *pt) | ||
615 | { | ||
616 | int i; | ||
617 | static const struct { | ||
618 | int w, h; | ||
619 | } cea_interlaced[] = { | ||
620 | { 1920, 1080 }, | ||
621 | { 720, 480 }, | ||
622 | { 1440, 480 }, | ||
623 | { 2880, 480 }, | ||
624 | { 720, 576 }, | ||
625 | { 1440, 576 }, | ||
626 | { 2880, 576 }, | ||
627 | }; | ||
628 | static const int n_sizes = | ||
629 | sizeof(cea_interlaced)/sizeof(cea_interlaced[0]); | ||
630 | |||
631 | if (!(pt->misc & DRM_EDID_PT_INTERLACED)) | ||
632 | return; | ||
633 | |||
634 | for (i = 0; i < n_sizes; i++) { | ||
635 | if ((mode->hdisplay == cea_interlaced[i].w) && | ||
636 | (mode->vdisplay == cea_interlaced[i].h / 2)) { | ||
637 | mode->vdisplay *= 2; | ||
638 | mode->vsync_start *= 2; | ||
639 | mode->vsync_end *= 2; | ||
640 | mode->vtotal *= 2; | ||
641 | mode->vtotal |= 1; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | mode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
646 | } | ||
647 | |||
590 | /** | 648 | /** |
591 | * drm_mode_detailed - create a new mode from an EDID detailed timing section | 649 | * drm_mode_detailed - create a new mode from an EDID detailed timing section |
592 | * @dev: DRM device (needed to create new mode) | 650 | * @dev: DRM device (needed to create new mode) |
@@ -622,8 +680,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
622 | return NULL; | 680 | return NULL; |
623 | } | 681 | } |
624 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { | 682 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { |
625 | printk(KERN_WARNING "integrated sync not supported\n"); | 683 | printk(KERN_WARNING "composite sync not supported\n"); |
626 | return NULL; | ||
627 | } | 684 | } |
628 | 685 | ||
629 | /* it is incorrect if hsync/vsync width is zero */ | 686 | /* it is incorrect if hsync/vsync width is zero */ |
@@ -653,15 +710,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
653 | mode->vsync_end = mode->vsync_start + vsync_pulse_width; | 710 | mode->vsync_end = mode->vsync_start + vsync_pulse_width; |
654 | mode->vtotal = mode->vdisplay + vblank; | 711 | mode->vtotal = mode->vdisplay + vblank; |
655 | 712 | ||
656 | /* perform the basic check for the detailed timing */ | ||
657 | if (mode->hsync_end > mode->htotal || | ||
658 | mode->vsync_end > mode->vtotal) { | ||
659 | drm_mode_destroy(dev, mode); | ||
660 | DRM_DEBUG_KMS("Incorrect detailed timing. " | ||
661 | "Sync is beyond the blank.\n"); | ||
662 | return NULL; | ||
663 | } | ||
664 | |||
665 | /* Some EDIDs have bogus h/vtotal values */ | 713 | /* Some EDIDs have bogus h/vtotal values */ |
666 | if (mode->hsync_end > mode->htotal) | 714 | if (mode->hsync_end > mode->htotal) |
667 | mode->htotal = mode->hsync_end + 1; | 715 | mode->htotal = mode->hsync_end + 1; |
@@ -670,8 +718,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
670 | 718 | ||
671 | drm_mode_set_name(mode); | 719 | drm_mode_set_name(mode); |
672 | 720 | ||
673 | if (pt->misc & DRM_EDID_PT_INTERLACED) | 721 | drm_mode_do_interlace_quirk(mode, pt); |
674 | mode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
675 | 722 | ||
676 | if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { | 723 | if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
677 | pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; | 724 | pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; |
@@ -834,8 +881,169 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid | |||
834 | return modes; | 881 | return modes; |
835 | } | 882 | } |
836 | 883 | ||
884 | /* | ||
885 | * XXX fix this for: | ||
886 | * - GTF secondary curve formula | ||
887 | * - EDID 1.4 range offsets | ||
888 | * - CVT extended bits | ||
889 | */ | ||
890 | static bool | ||
891 | mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing) | ||
892 | { | ||
893 | struct detailed_data_monitor_range *range; | ||
894 | int hsync, vrefresh; | ||
895 | |||
896 | range = &timing->data.other_data.data.range; | ||
897 | |||
898 | hsync = drm_mode_hsync(mode); | ||
899 | vrefresh = drm_mode_vrefresh(mode); | ||
900 | |||
901 | if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz) | ||
902 | return false; | ||
903 | |||
904 | if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq) | ||
905 | return false; | ||
906 | |||
907 | if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) { | ||
908 | /* be forgiving since it's in units of 10MHz */ | ||
909 | int max_clock = range->pixel_clock_mhz * 10 + 9; | ||
910 | max_clock *= 1000; | ||
911 | if (mode->clock > max_clock) | ||
912 | return false; | ||
913 | } | ||
914 | |||
915 | return true; | ||
916 | } | ||
917 | |||
918 | /* | ||
919 | * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will | ||
920 | * need to account for them. | ||
921 | */ | ||
922 | static int drm_gtf_modes_for_range(struct drm_connector *connector, | ||
923 | struct detailed_timing *timing) | ||
924 | { | ||
925 | int i, modes = 0; | ||
926 | struct drm_display_mode *newmode; | ||
927 | struct drm_device *dev = connector->dev; | ||
928 | |||
929 | for (i = 0; i < drm_num_dmt_modes; i++) { | ||
930 | if (mode_in_range(drm_dmt_modes + i, timing)) { | ||
931 | newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); | ||
932 | if (newmode) { | ||
933 | drm_mode_probed_add(connector, newmode); | ||
934 | modes++; | ||
935 | } | ||
936 | } | ||
937 | } | ||
938 | |||
939 | return modes; | ||
940 | } | ||
941 | |||
942 | static int drm_cvt_modes(struct drm_connector *connector, | ||
943 | struct detailed_timing *timing) | ||
944 | { | ||
945 | int i, j, modes = 0; | ||
946 | struct drm_display_mode *newmode; | ||
947 | struct drm_device *dev = connector->dev; | ||
948 | struct cvt_timing *cvt; | ||
949 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
950 | const u8 empty[3] = { 0, 0, 0 }; | ||
951 | |||
952 | for (i = 0; i < 4; i++) { | ||
953 | int uninitialized_var(width), height; | ||
954 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
955 | |||
956 | if (!memcmp(cvt->code, empty, 3)) | ||
957 | continue; | ||
958 | |||
959 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; | ||
960 | switch (cvt->code[1] & 0x0c) { | ||
961 | case 0x00: | ||
962 | width = height * 4 / 3; | ||
963 | break; | ||
964 | case 0x04: | ||
965 | width = height * 16 / 9; | ||
966 | break; | ||
967 | case 0x08: | ||
968 | width = height * 16 / 10; | ||
969 | break; | ||
970 | case 0x0c: | ||
971 | width = height * 15 / 9; | ||
972 | break; | ||
973 | } | ||
974 | |||
975 | for (j = 1; j < 5; j++) { | ||
976 | if (cvt->code[2] & (1 << j)) { | ||
977 | newmode = drm_cvt_mode(dev, width, height, | ||
978 | rates[j], j == 0, | ||
979 | false, false); | ||
980 | if (newmode) { | ||
981 | drm_mode_probed_add(connector, newmode); | ||
982 | modes++; | ||
983 | } | ||
984 | } | ||
985 | } | ||
986 | } | ||
987 | |||
988 | return modes; | ||
989 | } | ||
990 | |||
991 | static int add_detailed_modes(struct drm_connector *connector, | ||
992 | struct detailed_timing *timing, | ||
993 | struct edid *edid, u32 quirks, int preferred) | ||
994 | { | ||
995 | int i, modes = 0; | ||
996 | struct detailed_non_pixel *data = &timing->data.other_data; | ||
997 | int timing_level = standard_timing_level(edid); | ||
998 | int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); | ||
999 | struct drm_display_mode *newmode; | ||
1000 | struct drm_device *dev = connector->dev; | ||
1001 | |||
1002 | if (timing->pixel_clock) { | ||
1003 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | ||
1004 | if (!newmode) | ||
1005 | return 0; | ||
1006 | |||
1007 | if (preferred) | ||
1008 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | ||
1009 | |||
1010 | drm_mode_probed_add(connector, newmode); | ||
1011 | return 1; | ||
1012 | } | ||
1013 | |||
1014 | /* other timing types */ | ||
1015 | switch (data->type) { | ||
1016 | case EDID_DETAIL_MONITOR_RANGE: | ||
1017 | if (gtf) | ||
1018 | modes += drm_gtf_modes_for_range(connector, timing); | ||
1019 | break; | ||
1020 | case EDID_DETAIL_STD_MODES: | ||
1021 | /* Six modes per detailed section */ | ||
1022 | for (i = 0; i < 6; i++) { | ||
1023 | struct std_timing *std; | ||
1024 | struct drm_display_mode *newmode; | ||
1025 | |||
1026 | std = &data->data.timings[i]; | ||
1027 | newmode = drm_mode_std(dev, std, edid->revision, | ||
1028 | timing_level); | ||
1029 | if (newmode) { | ||
1030 | drm_mode_probed_add(connector, newmode); | ||
1031 | modes++; | ||
1032 | } | ||
1033 | } | ||
1034 | break; | ||
1035 | case EDID_DETAIL_CVT_3BYTE: | ||
1036 | modes += drm_cvt_modes(connector, timing); | ||
1037 | break; | ||
1038 | default: | ||
1039 | break; | ||
1040 | } | ||
1041 | |||
1042 | return modes; | ||
1043 | } | ||
1044 | |||
837 | /** | 1045 | /** |
838 | * add_detailed_modes - get detailed mode info from EDID data | 1046 | * add_detailed_info - get detailed mode info from EDID data |
839 | * @connector: attached connector | 1047 | * @connector: attached connector |
840 | * @edid: EDID block to scan | 1048 | * @edid: EDID block to scan |
841 | * @quirks: quirks to apply | 1049 | * @quirks: quirks to apply |
@@ -846,67 +1054,24 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid | |||
846 | static int add_detailed_info(struct drm_connector *connector, | 1054 | static int add_detailed_info(struct drm_connector *connector, |
847 | struct edid *edid, u32 quirks) | 1055 | struct edid *edid, u32 quirks) |
848 | { | 1056 | { |
849 | struct drm_device *dev = connector->dev; | 1057 | int i, modes = 0; |
850 | int i, j, modes = 0; | ||
851 | int timing_level; | ||
852 | |||
853 | timing_level = standard_timing_level(edid); | ||
854 | 1058 | ||
855 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { | 1059 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { |
856 | struct detailed_timing *timing = &edid->detailed_timings[i]; | 1060 | struct detailed_timing *timing = &edid->detailed_timings[i]; |
857 | struct detailed_non_pixel *data = &timing->data.other_data; | 1061 | int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); |
858 | struct drm_display_mode *newmode; | ||
859 | |||
860 | /* X server check is version 1.1 or higher */ | ||
861 | if (edid->version == 1 && edid->revision >= 1 && | ||
862 | !timing->pixel_clock) { | ||
863 | /* Other timing or info */ | ||
864 | switch (data->type) { | ||
865 | case EDID_DETAIL_MONITOR_SERIAL: | ||
866 | break; | ||
867 | case EDID_DETAIL_MONITOR_STRING: | ||
868 | break; | ||
869 | case EDID_DETAIL_MONITOR_RANGE: | ||
870 | /* Get monitor range data */ | ||
871 | break; | ||
872 | case EDID_DETAIL_MONITOR_NAME: | ||
873 | break; | ||
874 | case EDID_DETAIL_MONITOR_CPDATA: | ||
875 | break; | ||
876 | case EDID_DETAIL_STD_MODES: | ||
877 | for (j = 0; j < 6; i++) { | ||
878 | struct std_timing *std; | ||
879 | struct drm_display_mode *newmode; | ||
880 | |||
881 | std = &data->data.timings[j]; | ||
882 | newmode = drm_mode_std(dev, std, | ||
883 | edid->revision, | ||
884 | timing_level); | ||
885 | if (newmode) { | ||
886 | drm_mode_probed_add(connector, newmode); | ||
887 | modes++; | ||
888 | } | ||
889 | } | ||
890 | break; | ||
891 | default: | ||
892 | break; | ||
893 | } | ||
894 | } else { | ||
895 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | ||
896 | if (!newmode) | ||
897 | continue; | ||
898 | 1062 | ||
899 | /* First detailed mode is preferred */ | 1063 | /* In 1.0, only timings are allowed */ |
900 | if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) | 1064 | if (!timing->pixel_clock && edid->version == 1 && |
901 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | 1065 | edid->revision == 0) |
902 | drm_mode_probed_add(connector, newmode); | 1066 | continue; |
903 | 1067 | ||
904 | modes++; | 1068 | modes += add_detailed_modes(connector, timing, edid, quirks, |
905 | } | 1069 | preferred); |
906 | } | 1070 | } |
907 | 1071 | ||
908 | return modes; | 1072 | return modes; |
909 | } | 1073 | } |
1074 | |||
910 | /** | 1075 | /** |
911 | * add_detailed_mode_eedid - get detailed mode info from addtional timing | 1076 | * add_detailed_mode_eedid - get detailed mode info from addtional timing |
912 | * EDID block | 1077 | * EDID block |
@@ -920,12 +1085,9 @@ static int add_detailed_info(struct drm_connector *connector, | |||
920 | static int add_detailed_info_eedid(struct drm_connector *connector, | 1085 | static int add_detailed_info_eedid(struct drm_connector *connector, |
921 | struct edid *edid, u32 quirks) | 1086 | struct edid *edid, u32 quirks) |
922 | { | 1087 | { |
923 | struct drm_device *dev = connector->dev; | 1088 | int i, modes = 0; |
924 | int i, j, modes = 0; | ||
925 | char *edid_ext = NULL; | 1089 | char *edid_ext = NULL; |
926 | struct detailed_timing *timing; | 1090 | struct detailed_timing *timing; |
927 | struct detailed_non_pixel *data; | ||
928 | struct drm_display_mode *newmode; | ||
929 | int edid_ext_num; | 1091 | int edid_ext_num; |
930 | int start_offset, end_offset; | 1092 | int start_offset, end_offset; |
931 | int timing_level; | 1093 | int timing_level; |
@@ -944,8 +1106,8 @@ static int add_detailed_info_eedid(struct drm_connector *connector, | |||
944 | } | 1106 | } |
945 | 1107 | ||
946 | /* Chose real EDID extension number */ | 1108 | /* Chose real EDID extension number */ |
947 | edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? | 1109 | edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ? |
948 | MAX_EDID_EXT_NUM : edid->extensions; | 1110 | DRM_MAX_EDID_EXT_NUM : edid->extensions; |
949 | 1111 | ||
950 | /* Find CEA extension */ | 1112 | /* Find CEA extension */ |
951 | for (i = 0; i < edid_ext_num; i++) { | 1113 | for (i = 0; i < edid_ext_num; i++) { |
@@ -976,51 +1138,7 @@ static int add_detailed_info_eedid(struct drm_connector *connector, | |||
976 | for (i = start_offset; i < end_offset; | 1138 | for (i = start_offset; i < end_offset; |
977 | i += sizeof(struct detailed_timing)) { | 1139 | i += sizeof(struct detailed_timing)) { |
978 | timing = (struct detailed_timing *)(edid_ext + i); | 1140 | timing = (struct detailed_timing *)(edid_ext + i); |
979 | data = &timing->data.other_data; | 1141 | modes += add_detailed_modes(connector, timing, edid, quirks, 0); |
980 | /* Detailed mode timing */ | ||
981 | if (timing->pixel_clock) { | ||
982 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | ||
983 | if (!newmode) | ||
984 | continue; | ||
985 | |||
986 | drm_mode_probed_add(connector, newmode); | ||
987 | |||
988 | modes++; | ||
989 | continue; | ||
990 | } | ||
991 | |||
992 | /* Other timing or info */ | ||
993 | switch (data->type) { | ||
994 | case EDID_DETAIL_MONITOR_SERIAL: | ||
995 | break; | ||
996 | case EDID_DETAIL_MONITOR_STRING: | ||
997 | break; | ||
998 | case EDID_DETAIL_MONITOR_RANGE: | ||
999 | /* Get monitor range data */ | ||
1000 | break; | ||
1001 | case EDID_DETAIL_MONITOR_NAME: | ||
1002 | break; | ||
1003 | case EDID_DETAIL_MONITOR_CPDATA: | ||
1004 | break; | ||
1005 | case EDID_DETAIL_STD_MODES: | ||
1006 | /* Five modes per detailed section */ | ||
1007 | for (j = 0; j < 5; i++) { | ||
1008 | struct std_timing *std; | ||
1009 | struct drm_display_mode *newmode; | ||
1010 | |||
1011 | std = &data->data.timings[j]; | ||
1012 | newmode = drm_mode_std(dev, std, | ||
1013 | edid->revision, | ||
1014 | timing_level); | ||
1015 | if (newmode) { | ||
1016 | drm_mode_probed_add(connector, newmode); | ||
1017 | modes++; | ||
1018 | } | ||
1019 | } | ||
1020 | break; | ||
1021 | default: | ||
1022 | break; | ||
1023 | } | ||
1024 | } | 1142 | } |
1025 | 1143 | ||
1026 | return modes; | 1144 | return modes; |
@@ -1066,19 +1184,19 @@ static int drm_ddc_read_edid(struct drm_connector *connector, | |||
1066 | struct i2c_adapter *adapter, | 1184 | struct i2c_adapter *adapter, |
1067 | char *buf, int len) | 1185 | char *buf, int len) |
1068 | { | 1186 | { |
1069 | int ret; | 1187 | int i; |
1070 | 1188 | ||
1071 | ret = drm_do_probe_ddc_edid(adapter, buf, len); | 1189 | for (i = 0; i < 4; i++) { |
1072 | if (ret != 0) { | 1190 | if (drm_do_probe_ddc_edid(adapter, buf, len)) |
1073 | goto end; | 1191 | return -1; |
1074 | } | 1192 | if (drm_edid_is_valid((struct edid *)buf)) |
1075 | if (!edid_is_valid((struct edid *)buf)) { | 1193 | return 0; |
1076 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", | ||
1077 | drm_get_connector_name(connector)); | ||
1078 | ret = -1; | ||
1079 | } | 1194 | } |
1080 | end: | 1195 | |
1081 | return ret; | 1196 | /* repeated checksum failures; warn, but carry on */ |
1197 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", | ||
1198 | drm_get_connector_name(connector)); | ||
1199 | return -1; | ||
1082 | } | 1200 | } |
1083 | 1201 | ||
1084 | /** | 1202 | /** |
@@ -1096,7 +1214,7 @@ struct edid *drm_get_edid(struct drm_connector *connector, | |||
1096 | int ret; | 1214 | int ret; |
1097 | struct edid *edid; | 1215 | struct edid *edid; |
1098 | 1216 | ||
1099 | edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1), | 1217 | edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1), |
1100 | GFP_KERNEL); | 1218 | GFP_KERNEL); |
1101 | if (edid == NULL) { | 1219 | if (edid == NULL) { |
1102 | dev_warn(&connector->dev->pdev->dev, | 1220 | dev_warn(&connector->dev->pdev->dev, |
@@ -1114,14 +1232,14 @@ struct edid *drm_get_edid(struct drm_connector *connector, | |||
1114 | if (edid->extensions != 0) { | 1232 | if (edid->extensions != 0) { |
1115 | int edid_ext_num = edid->extensions; | 1233 | int edid_ext_num = edid->extensions; |
1116 | 1234 | ||
1117 | if (edid_ext_num > MAX_EDID_EXT_NUM) { | 1235 | if (edid_ext_num > DRM_MAX_EDID_EXT_NUM) { |
1118 | dev_warn(&connector->dev->pdev->dev, | 1236 | dev_warn(&connector->dev->pdev->dev, |
1119 | "The number of extension(%d) is " | 1237 | "The number of extension(%d) is " |
1120 | "over max (%d), actually read number (%d)\n", | 1238 | "over max (%d), actually read number (%d)\n", |
1121 | edid_ext_num, MAX_EDID_EXT_NUM, | 1239 | edid_ext_num, DRM_MAX_EDID_EXT_NUM, |
1122 | MAX_EDID_EXT_NUM); | 1240 | DRM_MAX_EDID_EXT_NUM); |
1123 | /* Reset EDID extension number to be read */ | 1241 | /* Reset EDID extension number to be read */ |
1124 | edid_ext_num = MAX_EDID_EXT_NUM; | 1242 | edid_ext_num = DRM_MAX_EDID_EXT_NUM; |
1125 | } | 1243 | } |
1126 | /* Read EDID including extensions too */ | 1244 | /* Read EDID including extensions too */ |
1127 | ret = drm_ddc_read_edid(connector, adapter, (char *)edid, | 1245 | ret = drm_ddc_read_edid(connector, adapter, (char *)edid, |
@@ -1164,8 +1282,8 @@ bool drm_detect_hdmi_monitor(struct edid *edid) | |||
1164 | goto end; | 1282 | goto end; |
1165 | 1283 | ||
1166 | /* Chose real EDID extension number */ | 1284 | /* Chose real EDID extension number */ |
1167 | edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? | 1285 | edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ? |
1168 | MAX_EDID_EXT_NUM : edid->extensions; | 1286 | DRM_MAX_EDID_EXT_NUM : edid->extensions; |
1169 | 1287 | ||
1170 | /* Find CEA extension */ | 1288 | /* Find CEA extension */ |
1171 | for (i = 0; i < edid_ext_num; i++) { | 1289 | for (i = 0; i < edid_ext_num; i++) { |
@@ -1222,7 +1340,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) | |||
1222 | if (edid == NULL) { | 1340 | if (edid == NULL) { |
1223 | return 0; | 1341 | return 0; |
1224 | } | 1342 | } |
1225 | if (!edid_is_valid(edid)) { | 1343 | if (!drm_edid_is_valid(edid)) { |
1226 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", | 1344 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", |
1227 | drm_get_connector_name(connector)); | 1345 | drm_get_connector_name(connector)); |
1228 | return 0; | 1346 | return 0; |
@@ -1296,6 +1414,8 @@ int drm_add_modes_noedid(struct drm_connector *connector, | |||
1296 | ptr->vdisplay > vdisplay) | 1414 | ptr->vdisplay > vdisplay) |
1297 | continue; | 1415 | continue; |
1298 | } | 1416 | } |
1417 | if (drm_mode_vrefresh(ptr) > 61) | ||
1418 | continue; | ||
1299 | mode = drm_mode_duplicate(dev, ptr); | 1419 | mode = drm_mode_duplicate(dev, ptr); |
1300 | if (mode) { | 1420 | if (mode) { |
1301 | drm_mode_probed_add(connector, mode); | 1421 | drm_mode_probed_add(connector, mode); |