drm/i915: Don't change the blank/sync width when calculating scaled modes
authorZhao Yakui <yakui.zhao@intel.com>
Mon, 22 Jun 2009 07:31:26 +0000 (15:31 +0800)
committerEric Anholt <eric@anholt.net>
Tue, 23 Jun 2009 02:35:08 +0000 (19:35 -0700)
Also, use the border instead of border minus one.

At the same time, make sure the horizontal border and hsync are even for
the LVDS that works in dual-channel mode. So both horizontal border and hsync
start are also changed to be even, even for the LVDS in single-channel mode.

https://bugs.freedesktop.org/show_bug.cgi?id=20951

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/intel_lvds.c

index f416ead71204d345db590c2eb373fa5dbc65b71c..9564ca44a977e71ab02d9a77e4df2f6dc52dc82d 100644 (file)
@@ -246,6 +246,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
        bool border = 0;
        int panel_ratio, desired_ratio, vert_scale, horiz_scale;
        int horiz_ratio, vert_ratio;
+       u32 hsync_width, vsync_width;
+       u32 hblank_width, vblank_width;
+       u32 hsync_pos, vsync_pos;
 
        /* Should never happen!! */
        if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
@@ -306,6 +309,14 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
                                        PFIT_FILTER_FUZZY;
 
+       hsync_width = adjusted_mode->crtc_hsync_end -
+                                       adjusted_mode->crtc_hsync_start;
+       vsync_width = adjusted_mode->crtc_vsync_end -
+                                       adjusted_mode->crtc_vsync_start;
+       hblank_width = adjusted_mode->crtc_hblank_end -
+                                       adjusted_mode->crtc_hblank_start;
+       vblank_width = adjusted_mode->crtc_vblank_end -
+                                       adjusted_mode->crtc_vblank_start;
        /*
         * Deal with panel fitting options. Figure out how to stretch the
         * image based on its aspect ratio & the current panel fitting mode.
@@ -339,23 +350,39 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                        bottom_border++;
                /* Set active & border values */
                adjusted_mode->crtc_hdisplay = mode->hdisplay;
+               /* Keep the boder be even */
+               if (right_border & 1)
+                       right_border++;
+               /* use the border directly instead of border minuse one */
                adjusted_mode->crtc_hblank_start = mode->hdisplay +
-                                               right_border - 1;
-               adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal -
-                                               left_border - 1;
+                                               right_border;
+               /* keep the blank width constant */
+               adjusted_mode->crtc_hblank_end =
+                       adjusted_mode->crtc_hblank_start + hblank_width;
+               /* get the hsync pos relative to hblank start */
+               hsync_pos = (hblank_width - hsync_width) / 2;
+               /* keep the hsync pos be even */
+               if (hsync_pos & 1)
+                       hsync_pos++;
                adjusted_mode->crtc_hsync_start =
-                               adjusted_mode->crtc_hblank_start;
+                               adjusted_mode->crtc_hblank_start + hsync_pos;
+               /* keep the hsync width constant */
                adjusted_mode->crtc_hsync_end =
-                               adjusted_mode->crtc_hblank_end;
+                               adjusted_mode->crtc_hsync_start + hsync_width;
                adjusted_mode->crtc_vdisplay = mode->vdisplay;
+               /* use the border instead of border minus one */
                adjusted_mode->crtc_vblank_start = mode->vdisplay +
-                                               bottom_border - 1;
-               adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal -
-                                               top_border - 1;
+                                               bottom_border;
+               /* keep the vblank width constant */
+               adjusted_mode->crtc_vblank_end =
+                               adjusted_mode->crtc_vblank_start + vblank_width;
+               /* get the vsync start postion relative to vblank start */
+               vsync_pos = (vblank_width - vsync_width) / 2;
                adjusted_mode->crtc_vsync_start =
-                               adjusted_mode->crtc_vblank_start;
+                               adjusted_mode->crtc_vblank_start + vsync_pos;
+               /* keep the vsync width constant */
                adjusted_mode->crtc_vsync_end =
-                               adjusted_mode->crtc_vblank_end;
+                               adjusted_mode->crtc_vblank_start + vsync_width;
                border = 1;
                break;
        case DRM_MODE_SCALE_ASPECT:
@@ -400,15 +427,32 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                                right_border = left_border;
                                if (mode->hdisplay & 1) /* odd resolutions */
                                        right_border++;
+                               /* keep the border be even */
+                               if (right_border & 1)
+                                       right_border++;
                                adjusted_mode->crtc_hdisplay = scaled_width;
+                               /* use border instead of border minus one */
                                adjusted_mode->crtc_hblank_start =
-                                       scaled_width + right_border - 1;
+                                       scaled_width + right_border;
+                               /* keep the hblank width constant */
                                adjusted_mode->crtc_hblank_end =
-                                adjusted_mode->crtc_htotal - left_border - 1;
+                                       adjusted_mode->crtc_hblank_start +
+                                                       hblank_width;
+                               /*
+                                * get the hsync start pos relative to
+                                * hblank start
+                                */
+                               hsync_pos = (hblank_width - hsync_width) / 2;
+                               /* keep the hsync_pos be even */
+                               if (hsync_pos & 1)
+                                       hsync_pos++;
                                adjusted_mode->crtc_hsync_start =
-                                       adjusted_mode->crtc_hblank_start;
+                                       adjusted_mode->crtc_hblank_start +
+                                                       hsync_pos;
+                               /* keept hsync width constant */
                                adjusted_mode->crtc_hsync_end =
-                                       adjusted_mode->crtc_hblank_end;
+                                       adjusted_mode->crtc_hsync_start +
+                                                       hsync_width;
                                border = 1;
                        } else if (panel_ratio < desired_ratio) { /* letter */
                                u32 scaled_height = mode->vdisplay *
@@ -424,14 +468,25 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                                if (mode->vdisplay & 1)
                                        bottom_border++;
                                adjusted_mode->crtc_vdisplay = scaled_height;
+                               /* use border instead of border minus one */
                                adjusted_mode->crtc_vblank_start =
-                                       scaled_height + bottom_border - 1;
+                                       scaled_height + bottom_border;
+                               /* keep the vblank width constant */
                                adjusted_mode->crtc_vblank_end =
-                                adjusted_mode->crtc_vtotal - top_border - 1;
+                                       adjusted_mode->crtc_vblank_start +
+                                                       vblank_width;
+                               /*
+                                * get the vsync start pos relative to
+                                * vblank start
+                                */
+                               vsync_pos = (vblank_width - vsync_width) / 2;
                                adjusted_mode->crtc_vsync_start =
-                                       adjusted_mode->crtc_vblank_start;
+                                       adjusted_mode->crtc_vblank_start +
+                                                       vsync_pos;
+                               /* keep the vsync width constant */
                                adjusted_mode->crtc_vsync_end =
-                                       adjusted_mode->crtc_vblank_end;
+                                       adjusted_mode->crtc_vsync_start +
+                                                       vsync_width;
                                border = 1;
                        } else {
                        /* Aspects match, Let hw scale both directions */