aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tridentfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-24 00:31:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:36 -0400
commit34dec24317d6824b7db172bb0072b909a9c376f2 (patch)
tree41826b7aca0f0f7df800743acd42ee0d421c4494 /drivers/video/tridentfb.c
parent2c86a0c26fbe8ea218f7a267645679fb78aba8a3 (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/tridentfb.c')
-rw-r--r--drivers/video/tridentfb.c35
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);