aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2012-04-13 16:33:40 -0400
committerDave Airlie <airlied@redhat.com>2012-04-20 07:57:56 -0400
commitb309bd37a1357bd4391dace247cceb9d9121d20a (patch)
tree0ac7b559daea685fe8a5b1fbab1209708de7a27b
parentb61b2140feaa6aca51c63db94aa5217cd82705d1 (diff)
drm/edid: Generate modes from extra_modes for range descriptors
Signed-off-by: Adam Jackson <ajax@redhat.com> Tested-by: Takashi Iwai <tiwai@suse.de> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_edid.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9363349fa034..38ee2f22304c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1037,11 +1037,61 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
1037 return modes; 1037 return modes;
1038} 1038}
1039 1039
1040static int
1041drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
1042 struct detailed_timing *timing)
1043{
1044 int i, modes = 0;
1045 struct drm_display_mode *newmode;
1046 struct drm_device *dev = connector->dev;
1047
1048 for (i = 0; i < num_extra_modes; i++) {
1049 const struct minimode *m = &extra_modes[i];
1050 newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0);
1051
1052 if (!mode_in_range(newmode, edid, timing)) {
1053 drm_mode_destroy(dev, newmode);
1054 continue;
1055 }
1056
1057 drm_mode_probed_add(connector, newmode);
1058 modes++;
1059 }
1060
1061 return modes;
1062}
1063
1064static int
1065drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
1066 struct detailed_timing *timing)
1067{
1068 int i, modes = 0;
1069 struct drm_display_mode *newmode;
1070 struct drm_device *dev = connector->dev;
1071 bool rb = drm_monitor_supports_rb(edid);
1072
1073 for (i = 0; i < num_extra_modes; i++) {
1074 const struct minimode *m = &extra_modes[i];
1075 newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0);
1076
1077 if (!mode_in_range(newmode, edid, timing)) {
1078 drm_mode_destroy(dev, newmode);
1079 continue;
1080 }
1081
1082 drm_mode_probed_add(connector, newmode);
1083 modes++;
1084 }
1085
1086 return modes;
1087}
1088
1040static void 1089static void
1041do_inferred_modes(struct detailed_timing *timing, void *c) 1090do_inferred_modes(struct detailed_timing *timing, void *c)
1042{ 1091{
1043 struct detailed_mode_closure *closure = c; 1092 struct detailed_mode_closure *closure = c;
1044 struct detailed_non_pixel *data = &timing->data.other_data; 1093 struct detailed_non_pixel *data = &timing->data.other_data;
1094 struct detailed_data_monitor_range *range = &data->data.range;
1045 1095
1046 if (data->type != EDID_DETAIL_MONITOR_RANGE) 1096 if (data->type != EDID_DETAIL_MONITOR_RANGE)
1047 return; 1097 return;
@@ -1049,6 +1099,29 @@ do_inferred_modes(struct detailed_timing *timing, void *c)
1049 closure->modes += drm_dmt_modes_for_range(closure->connector, 1099 closure->modes += drm_dmt_modes_for_range(closure->connector,
1050 closure->edid, 1100 closure->edid,
1051 timing); 1101 timing);
1102
1103 if (!version_greater(closure->edid, 1, 1))
1104 return; /* GTF not defined yet */
1105
1106 switch (range->flags) {
1107 case 0x02: /* secondary gtf, XXX could do more */
1108 case 0x00: /* default gtf */
1109 closure->modes += drm_gtf_modes_for_range(closure->connector,
1110 closure->edid,
1111 timing);
1112 break;
1113 case 0x04: /* cvt, only in 1.4+ */
1114 if (!version_greater(closure->edid, 1, 3))
1115 break;
1116
1117 closure->modes += drm_cvt_modes_for_range(closure->connector,
1118 closure->edid,
1119 timing);
1120 break;
1121 case 0x01: /* just the ranges, no formula */
1122 default:
1123 break;
1124 }
1052} 1125}
1053 1126
1054static int 1127static int