diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2008-07-24 00:31:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:36 -0400 |
commit | 34dec24317d6824b7db172bb0072b909a9c376f2 (patch) | |
tree | 41826b7aca0f0f7df800743acd42ee0d421c4494 /drivers/video | |
parent | 2c86a0c26fbe8ea218f7a267645679fb78aba8a3 (diff) |
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: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tridentfb.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index d896dee7b487..ff82ec1e5e4d 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -680,10 +680,12 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq) | |||
680 | 680 | ||
681 | d = 20000; | 681 | d = 20000; |
682 | for (k = 1; k >= 0; k--) | 682 | for (k = 1; k >= 0; k--) |
683 | for (m = 0; m < 32; m++) | 683 | for (m = 0; m < 32; m++) { |
684 | for (n = 0; n < 122; n++) { | 684 | n = 2 * (m + 2) - 8; |
685 | for (n = (n < 0 ? 0 : n); n < 122; n++) { | ||
685 | fi = ((14318l * (n + 8)) / (m + 2)) >> k; | 686 | fi = ((14318l * (n + 8)) / (m + 2)) >> k; |
686 | if ((di = abs(fi - freq)) < d) { | 687 | di = abs(fi - freq); |
688 | if (di <= d) { | ||
687 | d = di; | 689 | d = di; |
688 | best_n = n; | 690 | best_n = n; |
689 | best_m = m; | 691 | best_m = m; |
@@ -692,6 +694,7 @@ static void set_vclk(struct tridentfb_par *par, unsigned long freq) | |||
692 | if (fi > freq) | 694 | if (fi > freq) |
693 | break; | 695 | break; |
694 | } | 696 | } |
697 | } | ||
695 | 698 | ||
696 | if (is_oldclock(par->chip_id)) { | 699 | if (is_oldclock(par->chip_id)) { |
697 | lo = best_n | (best_m << 7); | 700 | lo = best_n | (best_m << 7); |
@@ -977,8 +980,8 @@ static int tridentfb_set_par(struct fb_info *info) | |||
977 | 980 | ||
978 | debug("enter\n"); | 981 | debug("enter\n"); |
979 | hdispend = var->xres / 8 - 1; | 982 | hdispend = var->xres / 8 - 1; |
980 | hsyncstart = (var->xres + var->right_margin) / 8 - 1; | 983 | hsyncstart = (var->xres + var->right_margin) / 8; |
981 | hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8 - 1; | 984 | hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8; |
982 | htotal = (var->xres + var->left_margin + var->right_margin + | 985 | htotal = (var->xres + var->left_margin + var->right_margin + |
983 | var->hsync_len) / 8 - 5; | 986 | var->hsync_len) / 8 - 5; |
984 | hblankstart = hdispend + 1; | 987 | hblankstart = hdispend + 1; |
@@ -991,8 +994,22 @@ static int tridentfb_set_par(struct fb_info *info) | |||
991 | vblankstart = vdispend + 1; | 994 | vblankstart = vdispend + 1; |
992 | vblankend = vtotal; | 995 | vblankend = vtotal; |
993 | 996 | ||
997 | if (info->var.vmode & FB_VMODE_INTERLACED) { | ||
998 | vtotal /= 2; | ||
999 | vdispend /= 2; | ||
1000 | vsyncstart /= 2; | ||
1001 | vsyncend /= 2; | ||
1002 | vblankstart /= 2; | ||
1003 | vblankend /= 2; | ||
1004 | } | ||
1005 | |||
994 | crtc_unlock(par); | 1006 | crtc_unlock(par); |
995 | write3CE(par, CyberControl, 8); | 1007 | write3CE(par, CyberControl, 8); |
1008 | tmp = 0xEB; | ||
1009 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | ||
1010 | tmp &= ~0x40; | ||
1011 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | ||
1012 | tmp &= ~0x80; | ||
996 | 1013 | ||
997 | if (par->flatpanel && var->xres < nativex) { | 1014 | if (par->flatpanel && var->xres < nativex) { |
998 | /* | 1015 | /* |
@@ -1000,7 +1017,7 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1000 | * than requested resolution decide whether | 1017 | * than requested resolution decide whether |
1001 | * we stretch or center | 1018 | * we stretch or center |
1002 | */ | 1019 | */ |
1003 | t_outb(par, 0xEB, VGA_MIS_W); | 1020 | t_outb(par, tmp | 0xC0, VGA_MIS_W); |
1004 | 1021 | ||
1005 | shadowmode_on(par); | 1022 | shadowmode_on(par); |
1006 | 1023 | ||
@@ -1010,7 +1027,7 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1010 | screen_stretch(par); | 1027 | screen_stretch(par); |
1011 | 1028 | ||
1012 | } else { | 1029 | } else { |
1013 | t_outb(par, 0x2B, VGA_MIS_W); | 1030 | t_outb(par, tmp, VGA_MIS_W); |
1014 | write3CE(par, CyberControl, 8); | 1031 | write3CE(par, CyberControl, 8); |
1015 | } | 1032 | } |
1016 | 1033 | ||
@@ -1071,6 +1088,10 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1071 | tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; | 1088 | tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; |
1072 | /* enable access extended memory */ | 1089 | /* enable access extended memory */ |
1073 | write3X4(par, CRTCModuleTest, tmp); | 1090 | write3X4(par, CRTCModuleTest, tmp); |
1091 | tmp = read3CE(par, MiscIntContReg) & ~0x4; | ||
1092 | if (info->var.vmode & FB_VMODE_INTERLACED) | ||
1093 | tmp |= 0x4; | ||
1094 | write3CE(par, MiscIntContReg, tmp); | ||
1074 | 1095 | ||
1075 | /* enable GE for text acceleration */ | 1096 | /* enable GE for text acceleration */ |
1076 | write3X4(par, GraphEngReg, 0x80); | 1097 | write3X4(par, GraphEngReg, 0x80); |