summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-09-03 09:33:47 +0800
committerDave Airlie <airlied@redhat.com>2009-09-07 16:04:15 +1000
commit559ee21d261a54c42594ef9405d27e9008eedf44 (patch)
tree474be3b0ca2645db1366c03753333b9f5c45a19f
parentaa9eaa1f0962152d0bde821149d82fe7b70a6f92 (diff)
drm/kms: try to find the std mode in DMT table
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>
-rw-r--r--drivers/gpu/drm/drm_edid.c40
-rw-r--r--drivers/gpu/drm/drm_modes.c11
2 files changed, 39 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index e64eb6bbce1..f84a98f2e37 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -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);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index ab6e70eadc5..49404ce1666 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -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)