aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhao Yakui2009-06-22 15:31:26 +0800
committerEric Anholt2009-06-22 19:35:08 -0700
commitaa0261f230105b86409e29bbe851b09830d93d50 (patch)
tree43e27301b555f4f2305730eba9152cc95986d17b
parent3fbe18d65d66054667aaee849bed74674bb50062 (diff)
drm/i915: Don't change the blank/sync width when calculating scaled modes
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>
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c91
1 files changed, 73 insertions, 18 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f416ead71204..9564ca44a977 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -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 */