[Intel-gfx] [DRM/I915][PATCH 3/3_v2] Get the modeline for standard timing in EDID by using CVT/GTF

yakui.zhao at intel.com yakui.zhao at intel.com
Mon Jun 22 07:17:10 CEST 2009


From: Zhao Yakui <yakui.zhao at intel.com>

   Create the standard timing modeline by using CVT/GFT algorithm while
interpreting the EDID.

   In course of interpreting the EDID, the timing level will be obtained,
which is used to determine whether the CVT/GTF algorithm is selected to
generate the modeline for the given hdisplay/vdisplay/vfresh_rate.
   In the UMS mode firstly it will check whether it can be found in
the DMT table. If it can be found, then the modeline is returned. Then the
timing_level is used to choose CVT/GTF.
   As there is no DMT table, no modeline is returned when timing level
is DMT. For the other two timing levels, the CVT/GTF will be called to
generate the required standard timing modeline.

Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
---
 drivers/gpu/drm/drm_edid.c |   69 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 801a0d0..c768f5e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -61,6 +61,10 @@
 /* use +hsync +vsync for detailed mode */
 #define EDID_QUIRK_DETAILED_SYNC_PP		(1 << 6)
 
+#define LEVEL_DMT	0
+#define LEVEL_GTF	1
+#define	LEVEL_CVT	2
+
 static struct edid_quirk {
 	char *vendor;
 	int product_id;
@@ -240,23 +244,27 @@ static void edid_fixup_preferred(struct drm_connector *connector,
 /**
  * drm_mode_std - convert standard mode info (width, height, refresh) into mode
  * @t: standard timing params
+ * @timing_level: standard timing level
  *
  * Take the standard timing params (in this case width, aspect, and refresh)
- * and convert them into a real mode using CVT.
+ * and convert them into a real mode using CVT/GTF/DMT.
  *
  * Punts for now, but should eventually use the FB layer's CVT based mode
  * generation code.
  */
 struct drm_display_mode *drm_mode_std(struct drm_device *dev,
-				      struct std_timing *t)
+				      struct std_timing *t,
+				      int timing_level)
 {
 	struct drm_display_mode *mode;
-	int hsize = t->hsize * 8 + 248, vsize;
-
-	mode = drm_mode_create(dev);
-	if (!mode)
-		return NULL;
-
+	int hsize, vsize;
+	int vfresh_rate;
+
+	/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
+	hsize = t->hsize * 8 + 248;
+	/* vfresh_rate = t->vfreq + 60 */
+	vfresh_rate = t->vfreq + 60;
+	/* the vdisplay is calculated based on the aspect ratio */
 	if (t->aspect_ratio == 0)
 		vsize = (hsize * 10) / 16;
 	else if (t->aspect_ratio == 1)
@@ -266,7 +274,25 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
 	else
 		vsize = (hsize * 9) / 16;
 
-	drm_mode_set_name(mode);
+	mode = NULL;
+	switch (timing_level) {
+	case LEVEL_DMT:
+		mode = drm_mode_create(dev);
+		if (mode) {
+			mode->hdisplay = hsize;
+			mode->vdisplay = vsize;
+			drm_mode_set_name(mode);
+		}
+		break;
+	case LEVEL_GTF:
+		mode = drm_gtf_mode(dev, hsize, vsize, vfresh_rate,
+					0, 0);
+		break;
+	case LEVEL_CVT:
+		mode = drm_cvt_mode(dev, hsize, vsize, vfresh_rate,
+					0, 0);
+		break;
+	}
 
 	return mode;
 }
@@ -447,6 +473,19 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e
 
 	return modes;
 }
+/**
+ * stanard_timing_level - get std. timing level(CVT/GTF/DMT)
+ * @edid: EDID block to scan
+ */
+static int standard_timing_level(struct edid *edid)
+{
+	if (edid->revision >= 2) {
+		if (edid->revision >= 4 && edid->default_gtf)
+			return LEVEL_CVT;
+		return LEVEL_GTF;
+	}
+	return LEVEL_DMT;
+}
 
 /**
  * add_standard_modes - get std. modes from EDID and add them
@@ -459,6 +498,9 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
 {
 	struct drm_device *dev = connector->dev;
 	int i, modes = 0;
+	int timing_level;
+
+	timing_level = standard_timing_level(edid);
 
 	for (i = 0; i < EDID_STD_TIMINGS; i++) {
 		struct std_timing *t = &edid->standard_timings[i];
@@ -468,7 +510,8 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
 		if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
 			continue;
 
-		newmode = drm_mode_std(dev, &edid->standard_timings[i]);
+		newmode = drm_mode_std(dev, &edid->standard_timings[i],
+					timing_level);
 		if (newmode) {
 			drm_mode_probed_add(connector, newmode);
 			modes++;
@@ -492,6 +535,9 @@ static int add_detailed_info(struct drm_connector *connector,
 {
 	struct drm_device *dev = connector->dev;
 	int i, j, modes = 0;
+	int timing_level;
+
+	timing_level = standard_timing_level(edid);
 
 	for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
 		struct detailed_timing *timing = &edid->detailed_timings[i];
@@ -537,7 +583,8 @@ static int add_detailed_info(struct drm_connector *connector,
 				struct drm_display_mode *newmode;
 
 				std = &data->data.timings[j];
-				newmode = drm_mode_std(dev, std);
+				newmode = drm_mode_std(dev, std,
+							timing_level);
 				if (newmode) {
 					drm_mode_probed_add(connector, newmode);
 					modes++;
-- 
1.5.4




More information about the Intel-gfx mailing list