Subject: Patch: Not change the blank/sync width while doing LVDS scaling From: Zhao Yakui Don't the change the blank/vsync width while doing LVDS scaling mode. And the border is used instead of border minus one. At the same time the horizontal border and hsync should be even for the LVDS that works in dual-channle 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 Acked-by : Jesse Barnes Signed-off-by: Zhao Yakui --- src/i830_lvds.c | 83 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 21 deletions(-) Index: xf86_video_intel/src/i830_lvds.c =================================================================== --- xf86_video_intel.orig/src/i830_lvds.c 2009-06-12 09:54:59.000000000 +0800 +++ xf86_video_intel/src/i830_lvds.c 2009-06-12 10:32:59.000000000 +0800 @@ -607,6 +607,9 @@ float horiz_ratio, vert_ratio; int left_border = 0, right_border = 0, top_border = 0, bottom_border = 0; int i; + uint32_t hsync_width, vsync_width; + uint32_t hblank_width, vblank_width; + uint32_t hsync_pos, vsync_pos; Bool border = 0; for (i = 0; i < xf86_config->num_output; i++) { @@ -663,6 +666,12 @@ pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | PFIT_FILTER_FUZZY; + hsync_width = adjusted_mode->CrtcHSyncEnd - adjusted_mode->CrtcHSyncStart; + vsync_width = adjusted_mode->CrtcVSyncEnd - adjusted_mode->CrtcVSyncStart; + hblank_width = adjusted_mode->CrtcHBlankEnd - + adjusted_mode->CrtcHBlankStart; + vblank_width = adjusted_mode->CrtcVBlankEnd - + adjusted_mode->CrtcVBlankStart; /* * Deal with panel fitting options. Figure out how to stretch the image * based on its aspect ratio & the current panel fitting mode. @@ -700,17 +709,34 @@ /* Set active & border values */ adjusted_mode->CrtcHDisplay = mode->HDisplay; - adjusted_mode->CrtcHBlankStart = mode->HDisplay + right_border - 1; - adjusted_mode->CrtcHBlankEnd = adjusted_mode->CrtcHTotal - - left_border - 1; - adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHBlankStart; - adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHBlankEnd; + /* keep the horizontal border be even */ + if (right_border & 1) + right_border++; + /* use the border directly instead of border minus one */ + adjusted_mode->CrtcHBlankStart = mode->HDisplay + right_border; + /* keep the blank width constant */ + adjusted_mode->CrtcHBlankEnd = adjusted_mode->CrtcHBlankStart + + hblank_width; + /* get the hsync start position relative to hblank start */ + hsync_pos = (hblank_width - hsync_width) / 2; + /* keep the hsync width constant and hsync start be even */ + if (hsync_pos & 1) + hsync_pos++; + adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHBlankStart + + hsync_pos; + adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + + hsync_width; adjusted_mode->CrtcVDisplay = mode->VDisplay; - adjusted_mode->CrtcVBlankStart = mode->VDisplay + bottom_border - 1; - adjusted_mode->CrtcVBlankEnd = adjusted_mode->CrtcVTotal - - top_border - 1; - adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVBlankStart; - adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVBlankEnd; + /* use the border instead of border minus one */ + adjusted_mode->CrtcVBlankStart = mode->VDisplay + bottom_border; + adjusted_mode->CrtcVBlankEnd = adjusted_mode->CrtcVBlankStart + + vblank_width; + /* get the vsync start position relative to vblank start */ + vsync_pos = (vblank_width - vsync_width) / 2; + adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVBlankStart + + vsync_pos; + adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + + vsync_width; border = 1; break; case FULL_ASPECT: @@ -758,13 +784,22 @@ if (mode->HDisplay & 1) /* odd resolutions */ right_border++; + /* keep the border be even */ + if (right_border & 1) + right_border++; adjusted_mode->CrtcHDisplay = scaled_width; - adjusted_mode->CrtcHBlankStart = scaled_width + - right_border - 1; - adjusted_mode->CrtcHBlankEnd = adjusted_mode->CrtcHTotal - - left_border - 1; - adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHBlankStart; - adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHBlankEnd; + adjusted_mode->CrtcHBlankStart = scaled_width + right_border; + adjusted_mode->CrtcHBlankEnd = adjusted_mode->CrtcHBlankStart + + hblank_width; + /* get the hsync start position relative to hblank start */ + hsync_pos = (hblank_width - hsync_width) / 2; + /* keep the hsync start be even */ + if (hsync_pos & 1) + hsync_pos++; + adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHBlankStart + + hsync_pos; + adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + + hsync_width; border = 1; } else if (panel_ratio < desired_ratio) { /* Letter */ unsigned long scaled_height = (float)mode->VDisplay * @@ -782,12 +817,18 @@ bottom_border++; adjusted_mode->CrtcVDisplay = scaled_height; + /* use the border instead of border minus one */ adjusted_mode->CrtcVBlankStart = scaled_height + - bottom_border - 1; - adjusted_mode->CrtcVBlankEnd = adjusted_mode->CrtcVTotal - - top_border - 1; - adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVBlankStart; - adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVBlankEnd; + bottom_border; + /* keep the Vblank width constant */ + adjusted_mode->CrtcVBlankEnd = adjusted_mode->CrtcVBlankStart + + vblank_width; + /* get the vsync start position relative to vblank start */ + vsync_pos = (vblank_width - vsync_width) / 2; + adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVBlankStart + + vsync_pos; + adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVBlankStart + + vsync_width; border = 1; } else { /* Aspects match, let hw scale both directions */ pfit_control |= VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |