drm/kms: try to find the std mode in DMT table
authorZhao Yakui <yakui.zhao@intel.com>
Thu, 3 Sep 2009 01:33:47 +0000 (09:33 +0800)
committerDave Airlie <airlied@redhat.com>
Mon, 7 Sep 2009 06:04:15 +0000 (16:04 +1000)
When we need to add the standard timing mode, we will firstly check whether it
can be found in DMT table by comparing the hdisplay/vdisplay/vfresh_rate.
If it can't be found, then we will use the cvt/gtf to add the required mode.
If it can be found, it will be returned.

At the same time the function of drm_mode_vrefresh is also fixed. It will
return the result of actual refresh_rate plus 0.5.
For example:
When the calculated value is 84.9, then the fresh_rate is 85.
When the calculated value is 70.02, then the fresh_rate is 70.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_modes.c

index e64eb6bbce1a9fe532b134afec12761a46114ae7..f84a98f2e37307a978f3d94f45dba4db0aecee41 100644 (file)
@@ -480,6 +480,26 @@ static struct drm_display_mode drm_dmt_modes[] = {
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
 };
 
+static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
+                       int hsize, int vsize, int fresh)
+{
+       int i, count;
+       struct drm_display_mode *ptr, *mode;
+
+       count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
+       mode = NULL;
+       for (i = 0; i < count; i++) {
+               ptr = &drm_dmt_modes[i];
+               if (hsize == ptr->hdisplay &&
+                       vsize == ptr->vdisplay &&
+                       fresh == drm_mode_vrefresh(ptr)) {
+                       /* get the expected default mode */
+                       mode = drm_mode_duplicate(dev, ptr);
+                       break;
+               }
+       }
+       return mode;
+}
 /**
  * drm_mode_std - convert standard mode info (width, height, refresh) into mode
  * @t: standard timing params
@@ -516,16 +536,22 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
                vsize = (hsize * 4) / 5;
        else
                vsize = (hsize * 9) / 16;
-
+       /* HDTV hack */
+       if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) {
+               mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
+               mode->hdisplay = 1366;
+               mode->vsync_start = mode->vsync_start - 1;
+               mode->vsync_end = mode->vsync_end - 1;
+               return mode;
+       }
        mode = NULL;
+       /* check whether it can be found in default mode table */
+       mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate);
+       if (mode)
+               return mode;
+
        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, vrefresh_rate, 0, 0);
index ab6e70eadc5822cdc0291ea6bb13b8fc248da7a5..49404ce1666ea320e38c0e0f00b7668437aa224d 100644 (file)
@@ -566,7 +566,9 @@ EXPORT_SYMBOL(drm_mode_height);
  * FIXME: why is this needed?  shouldn't vrefresh be set already?
  *
  * RETURNS:
- * Vertical refresh rate of @mode x 1000. For precision reasons.
+ * Vertical refresh rate. It will be the result of actual value plus 0.5.
+ * If it is 70.288, it will return 70Hz.
+ * If it is 59.6, it will return 60Hz.
  */
 int drm_mode_vrefresh(struct drm_display_mode *mode)
 {
@@ -576,14 +578,13 @@ int drm_mode_vrefresh(struct drm_display_mode *mode)
        if (mode->vrefresh > 0)
                refresh = mode->vrefresh;
        else if (mode->htotal > 0 && mode->vtotal > 0) {
+               int vtotal;
+               vtotal = mode->vtotal;
                /* work out vrefresh the value will be x1000 */
                calc_val = (mode->clock * 1000);
-
                calc_val /= mode->htotal;
-               calc_val *= 1000;
-               calc_val /= mode->vtotal;
+               refresh = (calc_val + vtotal / 2) / vtotal;
 
-               refresh = calc_val;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                        refresh *= 2;
                if (mode->flags & DRM_MODE_FLAG_DBLSCAN)