Commit 34dec243 authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Linus Torvalds

tridentfb: various pixclock and timing improvements

This patch fixes few issues related to timings and pixclock generation:

 - disallow the pixclocks with numerator lower than
   double denominator. This fixes display instability
   for some modes.
 - choose the pixelclock with the highest
   numerator and denominator values. This improve
   image quality and fixes display instability
   for some modes.
 - make interlaced modes work.
 - set synchronization pulses polarization
   correctly.
 - horizontal synchronization timing are now
   the same as generated by X.
Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2c86a0c2
...@@ -680,10 +680,12 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq) ...@@ -680,10 +680,12 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq)
d = 20000; d = 20000;
for (k = 1; k >= 0; k--) for (k = 1; k >= 0; k--)
for (m = 0; m < 32; m++) for (m = 0; m < 32; m++) {
for (n = 0; n < 122; n++) { n = 2 * (m + 2) - 8;
for (n = (n < 0 ? 0 : n); n < 122; n++) {
fi = ((14318l * (n + 8)) / (m + 2)) >> k; fi = ((14318l * (n + 8)) / (m + 2)) >> k;
if ((di = abs(fi - freq)) < d) { di = abs(fi - freq);
if (di <= d) {
d = di; d = di;
best_n = n; best_n = n;
best_m = m; best_m = m;
...@@ -692,6 +694,7 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq) ...@@ -692,6 +694,7 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq)
if (fi > freq) if (fi > freq)
break; break;
} }
}
if (is_oldclock(par->chip_id)) { if (is_oldclock(par->chip_id)) {
lo = best_n | (best_m << 7); lo = best_n | (best_m << 7);
...@@ -977,8 +980,8 @@ static int tridentfb_set_par(struct fb_info *info) ...@@ -977,8 +980,8 @@ static int tridentfb_set_par(struct fb_info *info)
debug("enter\n"); debug("enter\n");
hdispend = var->xres / 8 - 1; hdispend = var->xres / 8 - 1;
hsyncstart = (var->xres + var->right_margin) / 8 - 1; hsyncstart = (var->xres + var->right_margin) / 8;
hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8 - 1; hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
htotal = (var->xres + var->left_margin + var->right_margin + htotal = (var->xres + var->left_margin + var->right_margin +
var->hsync_len) / 8 - 5; var->hsync_len) / 8 - 5;
hblankstart = hdispend + 1; hblankstart = hdispend + 1;
...@@ -991,8 +994,22 @@ static int tridentfb_set_par(struct fb_info *info) ...@@ -991,8 +994,22 @@ static int tridentfb_set_par(struct fb_info *info)
vblankstart = vdispend + 1; vblankstart = vdispend + 1;
vblankend = vtotal; vblankend = vtotal;
if (info->var.vmode & FB_VMODE_INTERLACED) {
vtotal /= 2;
vdispend /= 2;
vsyncstart /= 2;
vsyncend /= 2;
vblankstart /= 2;
vblankend /= 2;
}
crtc_unlock(par); crtc_unlock(par);
write3CE(par, CyberControl, 8); write3CE(par, CyberControl, 8);
tmp = 0xEB;
if (var->sync & FB_SYNC_HOR_HIGH_ACT)
tmp &= ~0x40;
if (var->sync & FB_SYNC_VERT_HIGH_ACT)
tmp &= ~0x80;
if (par->flatpanel && var->xres < nativex) { if (par->flatpanel && var->xres < nativex) {
/* /*
...@@ -1000,7 +1017,7 @@ static int tridentfb_set_par(struct fb_info *info) ...@@ -1000,7 +1017,7 @@ static int tridentfb_set_par(struct fb_info *info)
* than requested resolution decide whether * than requested resolution decide whether
* we stretch or center * we stretch or center
*/ */
t_outb(par, 0xEB, VGA_MIS_W); t_outb(par, tmp | 0xC0, VGA_MIS_W);
shadowmode_on(par); shadowmode_on(par);
...@@ -1010,7 +1027,7 @@ static int tridentfb_set_par(struct fb_info *info) ...@@ -1010,7 +1027,7 @@ static int tridentfb_set_par(struct fb_info *info)
screen_stretch(par); screen_stretch(par);
} else { } else {
t_outb(par, 0x2B, VGA_MIS_W); t_outb(par, tmp, VGA_MIS_W);
write3CE(par, CyberControl, 8); write3CE(par, CyberControl, 8);
} }
...@@ -1071,6 +1088,10 @@ static int tridentfb_set_par(struct fb_info *info) ...@@ -1071,6 +1088,10 @@ static int tridentfb_set_par(struct fb_info *info)
tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
/* enable access extended memory */ /* enable access extended memory */
write3X4(par, CRTCModuleTest, tmp); write3X4(par, CRTCModuleTest, tmp);
tmp = read3CE(par, MiscIntContReg) & ~0x4;
if (info->var.vmode & FB_VMODE_INTERLACED)
tmp |= 0x4;
write3CE(par, MiscIntContReg, tmp);
/* enable GE for text acceleration */ /* enable GE for text acceleration */
write3X4(par, GraphEngReg, 0x80); write3X4(par, GraphEngReg, 0x80);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment