diff options
author | Adam Jackson <ajax@redhat.com> | 2012-04-13 16:33:40 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-04-20 07:57:56 -0400 |
commit | b309bd37a1357bd4391dace247cceb9d9121d20a (patch) | |
tree | 0ac7b559daea685fe8a5b1fbab1209708de7a27b | |
parent | b61b2140feaa6aca51c63db94aa5217cd82705d1 (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.c | 73 |
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 | ||
1040 | static int | ||
1041 | drm_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 | |||
1064 | static int | ||
1065 | drm_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 | |||
1040 | static void | 1089 | static void |
1041 | do_inferred_modes(struct detailed_timing *timing, void *c) | 1090 | do_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 | ||
1054 | static int | 1127 | static int |