Rev 1313 | Rev 1404 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1313 | Rev 1321 | ||
---|---|---|---|
Line 121... | Line 121... | ||
121 | * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's |
121 | * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's |
122 | * valid. |
122 | * valid. |
123 | */ |
123 | */ |
124 | static bool edid_is_valid(struct edid *edid) |
124 | static bool edid_is_valid(struct edid *edid) |
125 | { |
125 | { |
126 | int i; |
126 | int i, score = 0; |
127 | u8 csum = 0; |
127 | u8 csum = 0; |
128 | u8 *raw_edid = (u8 *)edid; |
128 | u8 *raw_edid = (u8 *)edid; |
Line 129... | Line 129... | ||
129 | 129 | ||
- | 130 | for (i = 0; i < sizeof(edid_header); i++) |
|
130 | if (memcmp(edid->header, edid_header, sizeof(edid_header))) |
131 | if (raw_edid[i] == edid_header[i]) |
- | 132 | score++; |
|
- | 133 | ||
131 | goto bad; |
134 | if (score == 8) ; |
132 | if (edid->version != 1) { |
135 | else if (score >= 6) { |
- | 136 | DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); |
|
- | 137 | memcpy(raw_edid, edid_header, sizeof(edid_header)); |
|
133 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
138 | } else |
134 | goto bad; |
- | |
135 | } |
- | |
136 | if (edid->revision > 4) |
- | |
Line 137... | Line 139... | ||
137 | DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); |
139 | goto bad; |
138 | 140 | ||
139 | for (i = 0; i < EDID_LENGTH; i++) |
141 | for (i = 0; i < EDID_LENGTH; i++) |
140 | csum += raw_edid[i]; |
142 | csum += raw_edid[i]; |
141 | if (csum) { |
143 | if (csum) { |
142 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); |
144 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); |
Line -... | Line 145... | ||
- | 145 | goto bad; |
|
- | 146 | } |
|
- | 147 | ||
- | 148 | if (edid->version != 1) { |
|
- | 149 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
|
- | 150 | goto bad; |
|
- | 151 | } |
|
- | 152 | ||
143 | goto bad; |
153 | if (edid->revision > 4) |
Line 144... | Line 154... | ||
144 | } |
154 | DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); |
145 | 155 | ||
146 | return 1; |
156 | return 1; |
Line 479... | Line 489... | ||
479 | /* 2560x1600@85HZ */ |
489 | /* 2560x1600@85HZ */ |
480 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, |
490 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, |
481 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, |
491 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, |
482 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
492 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
483 | }; |
493 | }; |
- | 494 | static const int drm_num_dmt_modes = |
|
- | 495 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
|
Line 484... | Line 496... | ||
484 | 496 | ||
485 | static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, |
497 | static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, |
486 | int hsize, int vsize, int fresh) |
498 | int hsize, int vsize, int fresh) |
487 | { |
499 | { |
488 | int i, count; |
500 | int i; |
Line 489... | Line -... | ||
489 | struct drm_display_mode *ptr, *mode; |
- | |
490 | 501 | struct drm_display_mode *ptr, *mode; |
|
491 | count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
502 | |
492 | mode = NULL; |
503 | mode = NULL; |
493 | for (i = 0; i < count; i++) { |
504 | for (i = 0; i < drm_num_dmt_modes; i++) { |
494 | ptr = &drm_dmt_modes[i]; |
505 | ptr = &drm_dmt_modes[i]; |
495 | if (hsize == ptr->hdisplay && |
506 | if (hsize == ptr->hdisplay && |
496 | vsize == ptr->vdisplay && |
507 | vsize == ptr->vdisplay && |
Line 832... | Line 843... | ||
832 | } |
843 | } |
Line 833... | Line 844... | ||
833 | 844 | ||
834 | return modes; |
845 | return modes; |
Line 835... | Line 846... | ||
835 | } |
846 | } |
836 | - | ||
837 | /** |
847 | |
838 | * add_detailed_modes - get detailed mode info from EDID data |
848 | /* |
839 | * @connector: attached connector |
849 | * XXX fix this for: |
840 | * @edid: EDID block to scan |
- | |
841 | * @quirks: quirks to apply |
- | |
842 | * |
850 | * - GTF secondary curve formula |
843 | * Some of the detailed timing sections may contain mode information. Grab |
851 | * - EDID 1.4 range offsets |
844 | * it and add it to the list. |
852 | * - CVT extended bits |
845 | */ |
853 | */ |
846 | static int add_detailed_info(struct drm_connector *connector, |
854 | static bool |
- | 855 | mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing) |
|
- | 856 | { |
|
- | 857 | struct detailed_data_monitor_range *range; |
|
- | 858 | int hsync, vrefresh; |
|
- | 859 | ||
- | 860 | range = &timing->data.other_data.data.range; |
|
- | 861 | ||
- | 862 | hsync = drm_mode_hsync(mode); |
|
- | 863 | vrefresh = drm_mode_vrefresh(mode); |
|
- | 864 | ||
- | 865 | if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz) |
|
- | 866 | return false; |
|
- | 867 | ||
- | 868 | if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq) |
|
- | 869 | return false; |
|
- | 870 | ||
- | 871 | if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) { |
|
- | 872 | /* be forgiving since it's in units of 10MHz */ |
|
- | 873 | int max_clock = range->pixel_clock_mhz * 10 + 9; |
|
- | 874 | max_clock *= 1000; |
|
- | 875 | if (mode->clock > max_clock) |
|
- | 876 | return false; |
|
- | 877 | } |
|
- | 878 | ||
- | 879 | return true; |
|
- | 880 | } |
|
- | 881 | ||
- | 882 | /* |
|
- | 883 | * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will |
|
- | 884 | * need to account for them. |
|
- | 885 | */ |
|
- | 886 | static int drm_gtf_modes_for_range(struct drm_connector *connector, |
|
- | 887 | struct detailed_timing *timing) |
|
- | 888 | { |
|
847 | struct edid *edid, u32 quirks) |
889 | int i, modes = 0; |
848 | { |
- | |
849 | struct drm_device *dev = connector->dev; |
- | |
Line -... | Line 890... | ||
- | 890 | struct drm_display_mode *newmode; |
|
- | 891 | struct drm_device *dev = connector->dev; |
|
- | 892 | ||
- | 893 | for (i = 0; i < drm_num_dmt_modes; i++) { |
|
850 | int i, j, modes = 0; |
894 | if (mode_in_range(drm_dmt_modes + i, timing)) { |
- | 895 | newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); |
|
- | 896 | if (newmode) { |
|
- | 897 | drm_mode_probed_add(connector, newmode); |
|
- | 898 | modes++; |
|
Line -... | Line 899... | ||
- | 899 | } |
|
- | 900 | } |
|
- | 901 | } |
|
851 | int timing_level; |
902 | |
852 | 903 | return modes; |
|
- | 904 | } |
|
853 | timing_level = standard_timing_level(edid); |
905 | |
854 | 906 | static int drm_cvt_modes(struct drm_connector *connector, |
|
- | 907 | struct detailed_timing *timing) |
|
- | 908 | { |
|
- | 909 | int i, j, modes = 0; |
|
Line 855... | Line 910... | ||
855 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { |
910 | struct drm_display_mode *newmode; |
856 | struct detailed_timing *timing = &edid->detailed_timings[i]; |
911 | struct drm_device *dev = connector->dev; |
857 | struct detailed_non_pixel *data = &timing->data.other_data; |
912 | struct cvt_timing *cvt; |
- | 913 | const int rates[] = { 60, 85, 75, 60, 50 }; |
|
858 | struct drm_display_mode *newmode; |
914 | |
859 | 915 | for (i = 0; i < 4; i++) { |
|
- | 916 | int width, height; |
|
860 | /* X server check is version 1.1 or higher */ |
917 | cvt = &(timing->data.other_data.data.cvt[i]); |
861 | if (edid->version == 1 && edid->revision >= 1 && |
918 | |
- | 919 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2; |
|
862 | !timing->pixel_clock) { |
920 | switch (cvt->code[1] & 0xc0) { |
863 | /* Other timing or info */ |
921 | case 0x00: |
864 | switch (data->type) { |
922 | width = height * 4 / 3; |
865 | case EDID_DETAIL_MONITOR_SERIAL: |
923 | break; |
866 | break; |
924 | case 0x40: |
- | 925 | width = height * 16 / 9; |
|
867 | case EDID_DETAIL_MONITOR_STRING: |
926 | break; |
868 | break; |
927 | case 0x80: |
- | 928 | width = height * 16 / 10; |
|
- | 929 | break; |
|
- | 930 | case 0xc0: |
|
- | 931 | width = height * 15 / 9; |
|
- | 932 | break; |
|
- | 933 | } |
|
- | 934 | ||
- | 935 | for (j = 1; j < 5; j++) { |
|
- | 936 | if (cvt->code[2] & (1 << j)) { |
|
- | 937 | newmode = drm_cvt_mode(dev, width, height, |
|
- | 938 | rates[j], j == 0, |
|
- | 939 | false, false); |
|
- | 940 | if (newmode) { |
|
- | 941 | drm_mode_probed_add(connector, newmode); |
|
- | 942 | modes++; |
|
- | 943 | } |
|
- | 944 | } |
|
- | 945 | } |
|
- | 946 | } |
|
- | 947 | ||
- | 948 | return modes; |
|
- | 949 | } |
|
- | 950 | ||
- | 951 | static int add_detailed_modes(struct drm_connector *connector, |
|
- | 952 | struct detailed_timing *timing, |
|
- | 953 | struct edid *edid, u32 quirks, int preferred) |
|
- | 954 | { |
|
- | 955 | int i, modes = 0; |
|
- | 956 | struct detailed_non_pixel *data = &timing->data.other_data; |
|
- | 957 | int timing_level = standard_timing_level(edid); |
|
- | 958 | int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); |
|
- | 959 | struct drm_display_mode *newmode; |
|
- | 960 | struct drm_device *dev = connector->dev; |
|
- | 961 | ||
- | 962 | if (timing->pixel_clock) { |
|
- | 963 | newmode = drm_mode_detailed(dev, edid, timing, quirks); |
|
- | 964 | if (!newmode) |
|
- | 965 | return 0; |
|
- | 966 | ||
- | 967 | if (preferred) |
|
- | 968 | newmode->type |= DRM_MODE_TYPE_PREFERRED; |
|
- | 969 | ||
- | 970 | drm_mode_probed_add(connector, newmode); |
|
869 | case EDID_DETAIL_MONITOR_RANGE: |
971 | return 1; |
- | 972 | } |
|
- | 973 | ||
870 | /* Get monitor range data */ |
974 | /* other timing types */ |
871 | break; |
975 | switch (data->type) { |
- | 976 | case EDID_DETAIL_MONITOR_RANGE: |
|
872 | case EDID_DETAIL_MONITOR_NAME: |
977 | if (gtf) |
873 | break; |
978 | modes += drm_gtf_modes_for_range(connector, timing); |
874 | case EDID_DETAIL_MONITOR_CPDATA: |
979 | break; |
Line 875... | Line 980... | ||
875 | break; |
980 | case EDID_DETAIL_STD_MODES: |
876 | case EDID_DETAIL_STD_MODES: |
981 | /* Six modes per detailed section */ |
877 | for (j = 0; j < 6; i++) { |
- | |
878 | struct std_timing *std; |
982 | for (i = 0; i < 6; i++) { |
879 | struct drm_display_mode *newmode; |
983 | struct std_timing *std; |
880 | 984 | struct drm_display_mode *newmode; |
|
881 | std = &data->data.timings[j]; |
985 | |
882 | newmode = drm_mode_std(dev, std, |
986 | std = &data->data.timings[i]; |
883 | edid->revision, |
987 | newmode = drm_mode_std(dev, std, edid->revision, |
884 | timing_level); |
988 | timing_level); |
- | 989 | if (newmode) { |
|
- | 990 | drm_mode_probed_add(connector, newmode); |
|
- | 991 | modes++; |
|
885 | if (newmode) { |
992 | } |
886 | drm_mode_probed_add(connector, newmode); |
993 | } |
887 | modes++; |
994 | break; |
888 | } |
- | |
889 | } |
- | |
890 | break; |
- | |
891 | default: |
- | |
892 | break; |
- | |
893 | } |
- | |
894 | } else { |
- | |
895 | newmode = drm_mode_detailed(dev, edid, timing, quirks); |
- | |
896 | if (!newmode) |
- | |
Line 897... | Line 995... | ||
897 | continue; |
995 | case EDID_DETAIL_CVT_3BYTE: |
898 | 996 | modes += drm_cvt_modes(connector, timing); |
|
- | 997 | break; |
|
- | 998 | default: |
|
- | 999 | break; |
|
- | 1000 | } |
|
- | 1001 | ||
- | 1002 | return modes; |
|
- | 1003 | } |
|
- | 1004 | ||
- | 1005 | /** |
|
- | 1006 | * add_detailed_info - get detailed mode info from EDID data |
|
- | 1007 | * @connector: attached connector |
|
- | 1008 | * @edid: EDID block to scan |
|
- | 1009 | * @quirks: quirks to apply |
|
- | 1010 | * |
|
- | 1011 | * Some of the detailed timing sections may contain mode information. Grab |
|
- | 1012 | * it and add it to the list. |
|
- | 1013 | */ |
|
- | 1014 | static int add_detailed_info(struct drm_connector *connector, |
|
- | 1015 | struct edid *edid, u32 quirks) |
|
- | 1016 | { |
|
- | 1017 | int i, modes = 0; |
|
- | 1018 | ||
- | 1019 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { |
|
- | 1020 | struct detailed_timing *timing = &edid->detailed_timings[i]; |
|
- | 1021 | int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); |
|
- | 1022 | ||
899 | /* First detailed mode is preferred */ |
1023 | /* In 1.0, only timings are allowed */ |
Line 900... | Line 1024... | ||
900 | if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) |
1024 | if (!timing->pixel_clock && edid->version == 1 && |
901 | newmode->type |= DRM_MODE_TYPE_PREFERRED; |
1025 | edid->revision == 0) |
- | 1026 | continue; |
|
902 | drm_mode_probed_add(connector, newmode); |
1027 | |
903 | 1028 | modes += add_detailed_modes(connector, timing, edid, quirks, |
|
904 | modes++; |
1029 | preferred); |
905 | } |
1030 | } |
906 | } |
1031 | |
Line 918... | Line 1043... | ||
918 | * it and add it to the list. |
1043 | * it and add it to the list. |
919 | */ |
1044 | */ |
920 | static int add_detailed_info_eedid(struct drm_connector *connector, |
1045 | static int add_detailed_info_eedid(struct drm_connector *connector, |
921 | struct edid *edid, u32 quirks) |
1046 | struct edid *edid, u32 quirks) |
922 | { |
1047 | { |
923 | struct drm_device *dev = connector->dev; |
- | |
924 | int i, j, modes = 0; |
1048 | int i, modes = 0; |
925 | char *edid_ext = NULL; |
1049 | char *edid_ext = NULL; |
926 | struct detailed_timing *timing; |
1050 | struct detailed_timing *timing; |
927 | struct detailed_non_pixel *data; |
- | |
928 | struct drm_display_mode *newmode; |
- | |
929 | int edid_ext_num; |
1051 | int edid_ext_num; |
930 | int start_offset, end_offset; |
1052 | int start_offset, end_offset; |
931 | int timing_level; |
1053 | int timing_level; |
Line 932... | Line 1054... | ||
932 | 1054 | ||
Line 974... | Line 1096... | ||
974 | end_offset = EDID_LENGTH; |
1096 | end_offset = EDID_LENGTH; |
975 | end_offset -= sizeof(struct detailed_timing); |
1097 | end_offset -= sizeof(struct detailed_timing); |
976 | for (i = start_offset; i < end_offset; |
1098 | for (i = start_offset; i < end_offset; |
977 | i += sizeof(struct detailed_timing)) { |
1099 | i += sizeof(struct detailed_timing)) { |
978 | timing = (struct detailed_timing *)(edid_ext + i); |
1100 | timing = (struct detailed_timing *)(edid_ext + i); |
979 | data = &timing->data.other_data; |
- | |
980 | /* Detailed mode timing */ |
- | |
981 | if (timing->pixel_clock) { |
- | |
982 | newmode = drm_mode_detailed(dev, edid, timing, quirks); |
1101 | modes += add_detailed_modes(connector, timing, edid, quirks, 0); |
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 | } |
1102 | } |
Line 1025... | Line 1103... | ||
1025 | 1103 | ||
1026 | return modes; |
1104 | return modes; |
Line 1064... | Line 1142... | ||
1064 | 1142 | ||
1065 | static int drm_ddc_read_edid(struct drm_connector *connector, |
1143 | static int drm_ddc_read_edid(struct drm_connector *connector, |
1066 | struct i2c_adapter *adapter, |
1144 | struct i2c_adapter *adapter, |
1067 | char *buf, int len) |
1145 | char *buf, int len) |
1068 | { |
1146 | { |
Line -... | Line 1147... | ||
- | 1147 | int i; |
|
1069 | int ret; |
1148 | |
1070 | 1149 | for (i = 0; i < 4; i++) { |
|
- | 1150 | if (drm_do_probe_ddc_edid(adapter, buf, len)) |
|
1071 | ret = drm_do_probe_ddc_edid(adapter, buf, len); |
1151 | return -1; |
1072 | if (ret != 0) { |
1152 | if (edid_is_valid((struct edid *)buf)) |
- | 1153 | return 0; |
|
1073 | goto end; |
1154 | } |
1074 | } |
1155 | |
1075 | if (!edid_is_valid((struct edid *)buf)) { |
1156 | /* repeated checksum failures; warn, but carry on */ |
1076 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", |
- | |
1077 | drm_get_connector_name(connector)); |
- | |
1078 | ret = -1; |
- | |
1079 | } |
1157 | dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", |
1080 | end: |
1158 | drm_get_connector_name(connector)); |
Line 1081... | Line 1159... | ||
1081 | return ret; |
1159 | return -1; |
1082 | } |
1160 | } |
1083 | 1161 | ||
Line 1294... | Line 1372... | ||
1294 | */ |
1372 | */ |
1295 | if (ptr->hdisplay > hdisplay || |
1373 | if (ptr->hdisplay > hdisplay || |
1296 | ptr->vdisplay > vdisplay) |
1374 | ptr->vdisplay > vdisplay) |
1297 | continue; |
1375 | continue; |
1298 | } |
1376 | } |
- | 1377 | if (drm_mode_vrefresh(ptr) > 61) |
|
- | 1378 | continue; |
|
1299 | mode = drm_mode_duplicate(dev, ptr); |
1379 | mode = drm_mode_duplicate(dev, ptr); |
1300 | if (mode) { |
1380 | if (mode) { |
1301 | drm_mode_probed_add(connector, mode); |
1381 | drm_mode_probed_add(connector, mode); |
1302 | num_modes++; |
1382 | num_modes++; |
1303 | } |
1383 | } |