diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2011-12-19 17:39:47 -0500 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-12-20 21:25:21 -0500 |
commit | 66cde97da7cbbc940cb3f3dbf9e8f0ac56431f8c (patch) | |
tree | 7d9ffe066cebc2724b95c585f26d19f62c4248a9 /drivers/video/s3fb.c | |
parent | 396fa99e0e58198f400110f2b6432b5b6522476b (diff) |
s3fb: fix Virge/VX
Add memory size detection for Virge/VX and small delay in mode setting (same
as in X.org driver) to fix blank screen problem.
Also adjust DTPC position to fix garbled screen in some modes (tested that
this adjustment does not break other cards - at least Trio32, Trio64V+,
Trio64V2/DX, Virge, Virge/DX).
Tested on ELSA Winner 2000AVI/3D.
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r-- | drivers/video/s3fb.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 946a949f4c7d..2c80246b18b8 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -727,7 +727,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
727 | if (par->chip == CHIP_988_VIRGE_VX) { | 727 | if (par->chip == CHIP_988_VIRGE_VX) { |
728 | vga_wcrt(par->state.vgabase, 0x50, 0x00); | 728 | vga_wcrt(par->state.vgabase, 0x50, 0x00); |
729 | vga_wcrt(par->state.vgabase, 0x67, 0x50); | 729 | vga_wcrt(par->state.vgabase, 0x67, 0x50); |
730 | 730 | msleep(10); /* screen remains blank sometimes without this */ | |
731 | vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); | 731 | vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); |
732 | vga_wcrt(par->state.vgabase, 0x66, 0x90); | 732 | vga_wcrt(par->state.vgabase, 0x66, 0x90); |
733 | } | 733 | } |
@@ -901,7 +901,8 @@ static int s3fb_set_par(struct fb_info *info) | |||
901 | 901 | ||
902 | /* Set Data Transfer Position */ | 902 | /* Set Data Transfer Position */ |
903 | hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; | 903 | hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; |
904 | value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1); | 904 | /* + 2 is needed for Virge/VX, does no harm on other cards */ |
905 | value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1); | ||
905 | svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); | 906 | svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); |
906 | 907 | ||
907 | memset_io(info->screen_base, 0x00, screen_size); | 908 | memset_io(info->screen_base, 0x00, screen_size); |
@@ -1216,6 +1217,31 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1216 | info->screen_size = 2 << 20; | 1217 | info->screen_size = 2 << 20; |
1217 | break; | 1218 | break; |
1218 | } | 1219 | } |
1220 | } else if (par->chip == CHIP_988_VIRGE_VX) { | ||
1221 | switch ((regval & 0x60) >> 5) { | ||
1222 | case 0: /* 2MB */ | ||
1223 | info->screen_size = 2 << 20; | ||
1224 | break; | ||
1225 | case 1: /* 4MB */ | ||
1226 | info->screen_size = 4 << 20; | ||
1227 | break; | ||
1228 | case 2: /* 6MB */ | ||
1229 | info->screen_size = 6 << 20; | ||
1230 | break; | ||
1231 | case 3: /* 8MB */ | ||
1232 | info->screen_size = 8 << 20; | ||
1233 | break; | ||
1234 | } | ||
1235 | /* off-screen memory */ | ||
1236 | regval = vga_rcrt(par->state.vgabase, 0x37); | ||
1237 | switch ((regval & 0x60) >> 5) { | ||
1238 | case 1: /* 4MB */ | ||
1239 | info->screen_size -= 4 << 20; | ||
1240 | break; | ||
1241 | case 2: /* 2MB */ | ||
1242 | info->screen_size -= 2 << 20; | ||
1243 | break; | ||
1244 | } | ||
1219 | } else | 1245 | } else |
1220 | info->screen_size = s3_memsizes[regval >> 5] << 10; | 1246 | info->screen_size = s3_memsizes[regval >> 5] << 10; |
1221 | info->fix.smem_len = info->screen_size; | 1247 | info->fix.smem_len = info->screen_size; |